Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Slow compile times with Tailwind #5745

Closed
dionysiusmarquis opened this issue Dec 5, 2020 · 13 comments
Closed

Slow compile times with Tailwind #5745

dionysiusmarquis opened this issue Dec 5, 2020 · 13 comments

Comments

@dionysiusmarquis
Copy link

dionysiusmarquis commented Dec 5, 2020

Is your feature request related to a problem? Please describe.
I tried to use Tailwind with Sapper. Even with the most basic setup the initial build time will go from ~2s to ~26s. I then tried to build the base Tailwind css outside of the Sapper build pipeline, this will take ~3s. The problem is that I'm not able to work on Tailwind theming etc. since I always have to wait 30s or with the other approach reload everything "by hand" instead of having sapper dev doing it for me properly.
I also tried copy pasting the generated Tailwind CSS into a Svelte components <style global>… - still same build time increase. Therefore It shouldn't be caused by preprocessing etc. I think this is due to the fact that every css will be considered "handwritten" and all Svelte css processing kicks in, even though it's actually a frameworks css that most likely doesn't need or even shouldn't be further processed.
At least in the context of Sapper It would be easier to just import the css globally and have a proper dev build running "out of the box" instead of handling it outside of Sapper and try to get it in sync with the sapper build pipeline.

Describe the solution you'd like
Something like <style plain> could work. plain just indicates that the css shouldn't/don't need to be processed by Svelte.

Describe alternatives you've considered
I will now try to write a rollup plugin to build Tailwind and then "inject" the result into an already processed css file in the Sapper build pipeline.

How important is this feature to you?
With my current "full setup" Sapper it takes ~1m to rebuild Tailwind. This is pretty unusable, especially if you are aware that "normally" this should only take a few seconds.

Additional context
sveltejs/svelte-preprocess#275
Hello World REPL with unmodified Tailwind base CSS (With preprocess global already applied - otherwise it wouldn't compile as It'll try to apply the component scope to every Tailwind definition - see: REPL)

@benmccann
Copy link
Member

@Conduitry
Copy link
Member

If you don't want Svelte to touch your CSS then (as long as you are using the appropriate bundler plugins) you should be able to have import './external_styles.css'; somewhere, which should remove the need for <style global> as well.

I personally haven't had difficulty with huge build times when using a single Svelte component whose job is to bring in all the Tailwind styles with a <style global> (with the normal Tailwind directives), but I haven't tried Tailwind v2 yet.

@dionysiusmarquis
Copy link
Author

@benmccann I know that solution. In terms of Sapper I couldn‘t reload the updated built global.css as it‘s cached by the service worker. You could exclude it there but then the global.css still isn‘t hashed e.g. Tbh that feels way to hacky for prod.

@Conduitry Yea also tried that. Then you can just use the rollup postcss plugin (which doesn‘t work with postcss8 atm 😬). But from there it‘s still hacky to get the extracted css into the sapper template and build pipeline

Currently I‘m using a custom rollup plugin that applies a postcss process on the corresponding svelte component css that‘s still In the rollup build pipeline. That way Tailwind gets build and applied after the svelte compiling. I‘m now back at 2-4s even with Tailwind updated instead of >1m. But that will only work for the client with emitCss enabled, I think

I still would prefer to be able to bypass svelte css processing at compile time. It‘s super hard to use something like Tailwind with sapper without that option. I wanted to create and update the project specific theme, but atm it feels very clunky and hacky to get an „expected“ dev workflow, because svelte „must“ process every css, no matter what.

@benmccann
Copy link
Member

benmccann commented Dec 5, 2020

the global.css still isn‘t hashed

That sounds it might be one of the main problems. I would support fixing that

@dionysiusmarquis
Copy link
Author

🤔 If sapper would also react to css coming from the build pipeline and additionally injecting them, could be another solution.
Not sure if updating/hashing the global.css inside the static folder and changing template.html is the best option here. But that would work as well, I guess

@benmccann
Copy link
Member

benmccann commented Dec 7, 2020

Is sveltejs/sapper#1660 is related to this?

@dionysiusmarquis
Copy link
Author

I realised that sapper already "injects" css files. So I just needed to change my import '…my-style.pcss' to import '…my-style.css'. After that I could easily add a simple project specific postcss plugin to the rollup build config. This would work, but unfortunately the sapper chunk hashes ignore these changes (as described in my sapper issue).

@dionysiusmarquis
Copy link
Author

dionysiusmarquis commented Dec 8, 2020

My current project specific plugin (still needs to be tested more), which processes all imported .css files through postcss and will also ensure "proper" sapper chunk hashes. With Tailwind/Postcss already set up in your project, you only need to add this plugin to your rollup config:

// MyComponent.svelte
<script>
  import 'src/styles/tailwind.css' // Sapper only injects `.css` files, so no `.pcss` here ._. 
…
import { createHash } from 'crypto'
import { existsSync } from 'fs'
import { readFile } from 'fs/promises'
import path from 'path'
import postcss from 'postcss'

import loadConfig from 'postcss-load-config'

const configFiles = ['postcss.config.js', 'tailwind.config.js']

export default function postcssImport () {
  let config
  const cssCache = {}
  return {
    name: 'postcss-import',
    augmentChunkHash (chunk) {
      // apply hashes to chunks (this isn't done properly by sapper atm)
      let hash
      for (const moduleId in chunk.modules) {
        const css = cssCache[moduleId]
        if (css) {
          if (!hash) {
            hash = createHash('sha256')
          }
          hash.update(css.hash)
        }
      }
      if (hash) {
        return hash.digest('hex')
      }
    },
    async buildStart () {
      if (!config) {
        config = await loadConfig()
      }
      configFiles.forEach(file => this.addWatchFile(file))
    },
    async load (id) {
      const idPath = path.parse(id)
      if (idPath.ext === '.css') {
        // ignore svelte css files created with `emitCss` enabled
        const isSvelteCss = existsSync(`${idPath.dir}/${idPath.name}.svelte`)
        if (isSvelteCss) return
        try {
          const content = await readFile(id, 'utf8')
          const { css, map } = await postcss(config.plugins).process(content, {
            from: id
          })
          // already create hashes based on the css result for fast `augmentChunkHash` hash creation
          const hash = createHash('sha256').update(css).digest('hex')
          cssCache[id] = { content, hash }
          return { code: css, map }
        } catch (error) {
          console.error(error)
        }
      }
    },
    watchChange (id) {
      // on config file change
      if (configFiles.some(file => id.includes(file))) {
        config = null
      }
    }
  }
}

@benmccann
Copy link
Member

That's awesome. Thanks so much for sharing!

I'm going to go ahead and close this since it sounds like it's possible to address without any changes in Svelte. I'd love to help you get the fix into Sapper though

@syffs
Copy link

syffs commented Mar 10, 2021

using windicss is a game changer in my experience. rollup -w rebuilds in milliseconds

@petrkoutnycz
Copy link

using windicss is a game changer in my experience. rollup -w rebuilds in milliseconds

Hi, have you used it together with SvelteKit or anything else...? Thanks.

@benmccann
Copy link
Member

Use https://github.com/svelte-add/tailwindcss which performs well

@mimoo
Copy link

mimoo commented Aug 18, 2021

I too have issues with tailwind in svelte (26s to compile).
The svelte-add plugin didn't work for me:

[!] Error: Unexpected character '@' (Note that you need plugins to import files that are not JavaScript)

EDIT: I'm trying windicss, but the install guide is lacking (https://windicss.org/integrations/svelte.html)

EDIT2: I found this which works out of the box: https://github.com/srmullen/sttv

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants