简体   繁体   English

Rollup.js - 让 PostCSS 处理整个 bundle.css 而不是来自 rollup-plugin-svelte 的单个文件

[英]Rollup.js - have PostCSS process whole bundle.css instead of individual files from rollup-plugin-svelte

I've tried several guides and many configurations, but can't get my rollup, postcss, and svelte bundle process to work quite right.我已经尝试了几个指南和许多配置,但无法让我的汇总、postcss 和 svelte 捆绑过程完全正常工作。

Right now the svelte plugin is extracting the css from my .svelte files and emitting it to the posctcss plugin, but it's doing it one file at a time instead of the entire bundle.现在 svelte 插件正在从我的 .svelte 文件中提取 css 并将其发送到 posctcss 插件,但它一次只处理一个文件而不是整个包。 This makes it so some functions in the purgecss and nanocss postcss plugins don't completely work because they need the entire bundle to do things like remove duplicate/redundant/unused css rules.这使得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',
            }),
    ],
}

How can I have rollup pass the entire bundle.css to postcss instead of one "file" at a time?我怎样才能让 rollup 将整个 bundle.css 传递给 postcss 而不是一次一个“文件”?

I had the same problem, preprocess goes file by file, so I had to actually include all my mixins and vars in every file, which is absolutely not a good solution.我遇到了同样的问题,预处理逐个文件进行,所以我实际上必须在每个文件中包含我所有的 mixin 和 vars,这绝对不是一个好的解决方案。

So for me the first solution was to remove postcss from sveltePreprocess, not emit the css file and to use postcss on the css bundle, that you get in the css function from svelte.所以对我来说,第一个解决方案是从 sveltePreprocess 中删除 postcss,而不是发出 css 文件,并在 css 包上使用 postcss,这是您从 svelte 的 css 函数中获得的。

You can then or (1) use postcss directly in the css function of svelte, and then emit the resulting css file in your dist directory, or (2) you can emit this file in a CSS directory, and have postcss-cli watch this directory and bundle everything然后你可以或者 (1) 直接在 svelte 的 css 函数中使用 postcss,然后在你的 dist 目录中发出生成的 css 文件,或者 (2) 你可以在 CSS 目录中发出这个文件,并让postcss-cli观察这个目录并捆绑一切

Solution 1解决方案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(),
  ],
};

and my postcss.config.js which returns a function that return an array of plugins:和我的 postcss.config.js,它返回一个返回插件数组的函数:

export default (options) => {
  const plugins = [
    require('postcss-preset-env')()
  ];

  if (options.isProd) {
    plugins.push(require('cssnano')({ autoprefixer: false }));
  }

  return plugins;
};

Solution 2解决方案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';

Conclusion结论

All in all, I don't like this methods, for exemple because I can't use nesting, as svelte throws an error if the css is not valid.总而言之,我不喜欢这种方法,例如因为我不能使用嵌套,因为如果 css 无效,svelte 会抛出错误。

I would prefer being able to use rollup-plugin-postcss after rollup-plugin-svelte , with emitCss set to false and the possibility to use rollup's this.emitFile in svelte css function, because since once the bundled file is emitted, we should be able to process it.我希望能够在rollup-plugin-svelte之后使用rollup-plugin-postcss ,将emitCss设置为 false 并且可以在 svelte css 函数中使用 rollup 的this.emitFile ,因为一旦捆绑文件被发出,我们应该能够处理它。

It seems there are some issues talking about using emitfile, let's hope it will happen sooner than later https://github.com/sveltejs/rollup-plugin-svelte/issues/71似乎在谈论使用emitfile 时存在一些问题,希望它早日发生https://github.com/sveltejs/rollup-plugin-svelte/issues/71

Can't say for sure, but when i compare your setup with mine the most striking difference is that i have:不能肯定,但是当我将您的设置与我的设置进行比较时,最显着的区别是:

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

in the svelte options additionally.另外在svelte选项中。

My whole svelte option looks like this:我的整个 svelte 选项如下所示:

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

Note, i'm using sveltePreprocess which would make your postcss superfluous, but i don't think that is causing your issue.请注意,我正在使用sveltePreprocess这会使您的postcss多余,但我认为这不会导致您的问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM