首页 > 解决方案 > Rollup.js - 让 PostCSS 处理整个 bundle.css 而不是 rollup-plugin-svelte 中的单个文件

问题描述

我已经尝试了几个指南和许多配置,但无法让我的 rollup、postcss 和 svelte 捆绑过程正常工作。

现在,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',
            }),
    ],
}

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

标签: javascriptnode.jssveltepostcssrollupjs

解决方案


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

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

然后,您可以或(1)直接在 svelte 的 css 函数中使用 postcss,然后在 dist 目录中发出生成的 css 文件,或者(2)您可以在 CSS 目录中发出此文件,并postcss-cli监视此目录并捆绑一切

解决方案 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-postcssafter rollup-plugin-svelteemitCss设置为 false 并且可以this.emitFile在 svelte css 函数中使用汇总,因为一旦发出捆绑文件,我们应该能够处理它。

似乎有一些关于使用 emitfile 的问题,我们希望它会尽快发生https://github.com/sveltejs/rollup-plugin-svelte/issues/71


推荐阅读