我正在从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;