Vue-cli: How can one chunk vendor CSS? (from SaSS)

Created on 4 Jan 2019  ยท  5Comments  ยท  Source: vuejs/vue-cli

Version

3.2.3

Reproduction link

https://stackoverflow.com/questions/53964974/vue-js-cli-3-how-can-i-create-a-vendor-bundle-for-css-sass

Environment info

System:
    OS: macOS 10.14.2
    CPU: (8) x64 Intel(R) Core(TM) i7-6820HQ CPU @ 2.70GHz
  Binaries:
    Node: 10.13.0 - ~/.nvm/versions/node/v10.13.0/bin/node
    Yarn: Not Found
    npm: 6.4.1 - ~/.nvm/versions/node/v10.13.0/bin/npm
  Browsers:
    Chrome: 71.0.3578.98
    Firefox: 64.0
    Safari: 12.0.2
  npmPackages:
    @vue/babel-preset-app:  3.2.2
    @vue/cli-overlay:  3.2.0
    @vue/cli-plugin-babel: 3.2.2 => 3.2.2
    @vue/cli-service: 3.2.3 => 3.2.3
    @vue/cli-shared-utils:  3.2.2
    @vue/component-compiler-utils:  2.4.0
    @vue/preload-webpack-plugin:  1.1.0
    @vue/web-component-wrapper:  1.2.0
    babel-helper-vue-jsx-merge-props:  2.0.3
    babel-plugin-transform-vue-jsx:  4.0.1
    vue: 2.5.21 => 2.5.21
    vue-hot-reload-api:  2.3.1
    vue-loader:  15.4.2
    vue-router: 3.0.2 => 3.0.2
    vue-style-loader:  4.1.2
    vue-template-compiler: 2.5.21 => 2.5.21
    vue-template-es2015-compiler:  1.6.0
    vuex: 3.0.1 => 3.0.1
  npmGlobalPackages:
    @vue/cli: 3.2.1

Steps to reproduce

npm run build

What is expected?

chuck vendor SaSS to a separate file, similar to how chunks-vendor.js is handled

What is actually happening?

all SaSS is transpiled to one CSS file


I have tried every which way I can think to chunk out to a vendor CSS file to no avail. The issue details and expected output is thoroughly demonstrated through a question (unanswered) on StackOverflow: https://stackoverflow.com/questions/53964974/vue-js-cli-3-how-can-i-create-a-vendor-bundle-for-css-sass

Most helpful comment

To clarify even further and to get straight to the point, a freshly created app via vue-create with the following vue.config.js...

module.exports = {
  chainWebpack: config => {
    config.optimization.splitChunks({
      cacheGroups: {
        vendorStyles: {
          name: 'vendor',
          test(module) {
            return (
              /node_modules/.test(module.context) &&
              !/\.css$/.test(module.request)
            );
          },
          chunks: 'all',
          enforce: true
        }
      }
    });
  }
};

With an external dependency on minireset.css


imported via the following <style> tag will yield...

<style lang="scss">
    @import "../node_modules/minireset.css/minireset.sass";
</style>

dist โ”œโ”€โ”€ css | โ””โ”€โ”€ app.[id].css 0.91 kb


imported via the following <script> tag will yield...

<script>
    import 'minireset.css/minireset.sass';
</script>

dist โ”œโ”€โ”€ css | โ”œโ”€โ”€ app.[id].css 0.57 kb | โ””โ”€โ”€ vendor.[id].css 0.33 kb


Why is there a discrepancy and how can I mirror the behavior of the <script> to the <style> tag to both yield the two CSS files?

All 5 comments

As an update, an answer rolled in on my bountied StackOverflow question which proposed the solution to simply relocate style imports from the <style lang="scss"> blocks to the <script>blocks - which works well - but, is there a known limitation here? I'm mostly happy with the workaround, but crave the ability to import my external SaSS files through the style block with native language imports to later be chunked out. Thoughts?

To clarify even further and to get straight to the point, a freshly created app via vue-create with the following vue.config.js...

module.exports = {
  chainWebpack: config => {
    config.optimization.splitChunks({
      cacheGroups: {
        vendorStyles: {
          name: 'vendor',
          test(module) {
            return (
              /node_modules/.test(module.context) &&
              !/\.css$/.test(module.request)
            );
          },
          chunks: 'all',
          enforce: true
        }
      }
    });
  }
};

With an external dependency on minireset.css


imported via the following <style> tag will yield...

<style lang="scss">
    @import "../node_modules/minireset.css/minireset.sass";
</style>

dist โ”œโ”€โ”€ css | โ””โ”€โ”€ app.[id].css 0.91 kb


imported via the following <script> tag will yield...

<script>
    import 'minireset.css/minireset.sass';
</script>

dist โ”œโ”€โ”€ css | โ”œโ”€โ”€ app.[id].css 0.57 kb | โ””โ”€โ”€ vendor.[id].css 0.33 kb


Why is there a discrepancy and how can I mirror the behavior of the <script> to the <style> tag to both yield the two CSS files?

@sodatea ๆˆ‘ไนŸ้‡ๅˆฐ็ฑปไผผ็š„้œ€ๆฑ‚๏ผŒ่ฏท้—ฎ่ฏฅๆ€Žไนˆ้…็ฝฎๅ‘ข

Same issue here, I need some scss files to be compiled into separate file but no matter what I try all scss files are bundled in the componentName.css. putting the import in