【问题标题】:Rollup.js - have PostCSS process whole bundle.css instead of individual files from rollup-plugin-svelteRollup.js - 让 PostCSS 处理整个 bundle.css 而不是 rollup-plugin-svelte 中的单个文件
【发布时间】:2020-07-20 21:21:08
【问题描述】:

我尝试了多个指南和许多配置,但无法让我的 rollup、postcss 和 svelte bundle 流程正常工作。

现在 svelte 插件正在从我的 .svelte 文件中提取 css 并将其发送到 posctcss 插件,但它一次只处理一个文件而不是整个包。这使得 purgecss 和 nanocss postcss 插件中的某些功能不能完全工作,因为它们需要整个包来执行诸如删除重复/冗余/未使用的 css 规则之类的事情。

// rollup.config.js
import svelte from 'rollup-plugin-svelte'
import resolve from 'rollup-plugin-node-resolve'
import commonjs from 'rollup-plugin-commonjs'
import livereload from 'rollup-plugin-livereload'
import { terser } from 'rollup-plugin-terser'
import rollup_start_dev from './rollup_start_dev'
import builtins from 'rollup-plugin-node-builtins'
import postcss from 'rollup-plugin-postcss'

const production = !process.env.ROLLUP_WATCH

export default {
    input: 'src/main.js',
    output: {
        sourcemap: true,
        format: 'iife',
        name: 'app',
        file: 'public/bundle.js',
    },
    plugins: [
        svelte({
            dev: !production,
            emitCss: true,
        }),
        postcss({
            extract: true,
            sourceMap: true,
        }),
        builtins(),
        resolve({
            browser: true,
            dedupe: importee =>
                importee === 'svelte' || importee.startsWith('svelte/'),
        }),
        commonjs(),
        !production && rollup_start_dev,
        !production && livereload('public'),
        production && terser(),
    ],
    watch: {
        clearScreen: false,
    },
}
// postcss.config.js
const production = !process.env.ROLLUP_WATCH
const purgecss = require('@fullhuman/postcss-purgecss')


module.exports = {
    plugins: [
        require('postcss-import')(),
        require('tailwindcss'),
        require('autoprefixer'),
        production &&
            purgecss({
                content: ['./src/**/*.svelte', './src/**/*.html', './public/**/*.html'],
                css: ['./src/**/*.css'],
                whitelistPatterns: [/svelte-/],
                defaultExtractor: content => content.match(/[\w-/:]+(?<!:)/g) || [],
            }),
        production &&
            require('cssnano')({
                preset: 'default',
            }),
    ],
}

如何让 rollup 一次将整个 bundle.css 传递给 postcss 而不是一个“文件”?

【问题讨论】:

    标签: javascript node.js svelte postcss rollupjs


    【解决方案1】:

    我遇到了同样的问题,预处理是逐个文件进行的,所以我实际上必须在每个文件中包含我所有的 mixins 和 var,这绝对不是一个好的解决方案。

    所以对我来说,第一个解决方案是从 sveltePreprocess 中删除 postcss,而不是发出 css 文件并在 css 包上使用 postcss,您可以从 svelte 中获得 css 函数。

    然后您可以或 (1) 在 svelte 的 css 函数中直接使用 postcss,然后在 dist 目录中发出生成的 css 文件,或者 (2) 您可以在 CSS 目录中发出此文件,并拥有 @987654322 @看这个目录并捆绑所有东西

    解决方案 1

    // rollup.config.js
    
    // rollup.config.js
    import svelte from 'rollup-plugin-svelte';
    import resolve from 'rollup-plugin-node-resolve';
    
    import postcss from 'postcss';
    import postcssConfig from './postcss.config.js';
    const postcssPlugins = postcssConfig({});
    const postcssProcessor = postcss(postcssPlugins);
    
    export default {
      input: 'src/main.js',
      output: {
        file: 'public/bundle.js',
        format: 'iife',
      },
      plugins: [
        svelte({
          emitCss: false,
          css: async (css) => {
            const result = await postcssProcessor.process(css.code);
            css.code = result.css;
            css.write('public/bundle.css');
          },
        }),
        resolve(),
      ],
    };
    
    

    还有我的 postcss.config.js,它返回一个返回插件数组的函数:

    export default (options) => {
      const plugins = [
        require('postcss-preset-env')()
      ];
    
      if (options.isProd) {
        plugins.push(require('cssnano')({ autoprefixer: false }));
      }
    
      return plugins;
    };
    

    解决方案 2

    // rollup.config.js
    import svelte from 'rollup-plugin-svelte';
    import resolve from 'rollup-plugin-node-resolve';
    
    export default {
      input: 'src/main.js',
      output: {
        file: 'public/bundle.js',
        format: 'iife',
      },
      plugins: [
        svelte({
          emitCss: false,
          css: async (css) => {
            css.write('css/svelte-bundle.css');
          },
        }),
        resolve(),
      ],
    };
    
    
    // package.json
    {
      //...
      "scripts": {
        "dev": "npm-run-all --parallel js:watch css:watch",
        "js:watch": "rollup -c -w",
        "css:watch": "postcss css/app.css --dir dist/ --watch",
      },
    }
    
    /* css/app.css */
    @import 'vars.css';
    @import 'mixins.css';
    
    /* all other code ... */
    
    /* and svelte-bundle, which will trigger a bundling with postcss everytime it is emitted */
    @import 'svelte-bundle.css';
    

    结论

    总而言之,我不喜欢这种方法,例如因为我不能使用嵌套,因为如果 css 无效,svelte 会抛出错误。

    我希望能够在rollup-plugin-svelte 之后使用rollup-plugin-postcss,将emitCss 设置为false,并且可以在svelte css 函数中使用rollup 的this.emitFile,因为一旦发出捆绑文件,我们应该能够处理它。

    使用emitfile似乎有些问题,希望早日解决https://github.com/sveltejs/rollup-plugin-svelte/issues/71

    【讨论】:

      【解决方案2】:

      不能肯定地说,但是当我将您的设置与我的设置进行比较时,最显着的区别是我有:

      css: css => {
                      css.write('public/build/bundle.css');
                  }
      

      另外在苗条选项中。

      我的整个苗条选项如下所示:

      svelte({
          preprocess: sveltePreprocess({ postcss: true }),
          dev: !production,
          css: css => {
              css.write('public/build/bundle.css');
          }
      })
      

      请注意,我使用的是 sveltePreprocess,这会使您的 postcss 变得多余,但我认为这不会导致您的问题。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-03-29
        • 2021-07-07
        • 2020-05-10
        • 2023-04-01
        • 1970-01-01
        • 1970-01-01
        • 2021-03-14
        相关资源
        最近更新 更多