我正在从gulp迁移到webpack设置 . 我希望webpack处理我的js和css资产并将它们打包成捆绑包 . 我已经设置了2个webpack配置文件:一个用于js,一个用于css .

我项目中css和js资产的总大小相似:每个部分有70个文件(400kb缩小) .

我的问题与处理css资产与js相比时webpack性能不佳有关 .

比较:

  • JS build(首次运行):15-30秒

  • JS build(带缓存):2秒

  • CSS构建(首次运行):15秒

  • CSS构建(带缓存):10秒

显然,CSS构建器不像CSS部分那样有效地使用缓存 . 说实话,我认为它根本不使用缓存(node_modules / .cache没有任何相关的东西),第二次运行更快的唯一原因是文件系统预热 .

Watch 模式中的问题更大 . 我做了一个测试,我在监视模式下运行webpack并修改一个小文件(只有几行),它必须包含在一个更大的包中:

  • JS更新:150ms

  • CSS更新:1200-2000ms

CSS构建器在这里表现不佳 . 此外,捆绑包越大,更新它们所需的时间就越长,即使在应该立即编译的小文件中进行更改也是如此 .

此外,似乎增加入口点的数量也会对更新时间产生负面影响 . 更多条目=更新速度较慢,即使更新仅影响一个小文件 .

我试过玩 cache-loader 并将它放在提取插件之前和之后 . 老实说,它没有多大帮助 . 当缓存加载器放在提取插件前面时,在监视模式下不会发出css(只有js文件) . 在提取器之后放置缓存加载器可以稍微改善 生产环境 构建,但会减慢监视模式更新速度 .

我目前的猜测是sass加载器不使用缓存,并且在每个模块更新时,必须从头开始编译整个bundle并通过sass> postcss> css>再次提取管道 . 我想知道是否将导入管理委托给 postcss-import 并在postcss之后运行sass会做得更好 . 我曾尝试为 postcss-import 编写兼容sass的导入解析器 . 它似乎在一个小的测试环境中工作得更快,但在我们的真实项目中使用它会导致webpack崩溃:(没有足够的时间来找出原因发生的原因 .

如何改善当前设置的CSS构建时间?

我的JS和CSS配置如下 .

JS:

const path  = require('path');
const merge = require('webpack-merge');
const EntryPlugin = require('webpack-watched-glob-entries-plugin');
const dir = require('./node/dirconfig');

// use NODE_ENV var to switch between production and development
const devel = (process.env.NODE_ENV == 'development');

// base config for both prod and devel modes
let config = 
{
    name: 'scripts',

    // webpack preset
    // this should take care of production optimizations automatically
    mode: devel ? 'development' : 'production',

    // use all js files inside bundle dir as entries
    entry: EntryPlugin.getEntries(
        dir.assets + '/js/bundle/*.js'
    ),

    output: {
        path: dir.static + '/js',
        filename: "[name].js"
    },

    externals: {
        jquery: 'jQuery'
    },

    resolve: {
        modules: [dir.assets + '/js', 'node_modules']
    },

    module: {
        rules: [
            {
                test: /\.js$/,
                exclude: /node_modules/,
                use: {
                    loader: 'babel-loader',
                    options: {
                        cacheDirectory: true,
                    },
                },
            },
        ]
    },

    plugins: [
        new EntryPlugin(),
    ],
};


// additional config for development mode
const development = 
{
    // add eslint loader
    module: {
        rules: [
            {
                enforce: "pre", // make sure this rule gets executed first
                test: /\.js$/,
                exclude: /(node_modules)/,
                use: {
                    loader: 'eslint-loader',
                    options: {
                        cache: true,
                    },
                },
            },
        ]
    }
};

module.exports = merge(config, devel ? development : {});

CSS:

const path = require('path');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const EntryPlugin = require('webpack-watched-glob-entries-plugin');
const dir = require('./node/dirconfig');

// use NODE_ENV var to switch between production and development
const devel = (process.env.NODE_ENV == 'development');

// base config for both prod and devel modes
let config = 
{
    name: 'styles',

    // webpack preset
    mode: devel ? 'development' : 'production',

    // use all .scss files which don't start with _ as entries
    entry: EntryPlugin.getEntries(
        dir.assets + '/sass/**/!(_*).scss'
    ),

    output: {
        path: dir.static + '/css',
        filename: "[name].js"
    },

    // enable sourcemaps in devel mode
    devtool: devel ? 'inline-source-map' : false,

    module: {
        rules: [
            {
                test: /\.scss$/,
                use: [
                    MiniCssExtractPlugin.loader,
                    // 'cache-loader',
                    {
                        loader: 'css-loader',
                        options: {
                            sourceMap: devel,
                        }
                    },
                    {
                        loader: 'postcss-loader',
                        options: {
                            sourceMap: devel,
                        },
                    },
                    {
                        loader: 'sass-loader',
                        options: {
                            sourceMap: devel,
                        }
                    },
                ]
            },
        ]
    },

    plugins: [
        new MiniCssExtractPlugin({
            filename: "[name].css", // relative to path setting in the output section
        }),
        new EntryPlugin()
    ],
};

module.exports = config;