【发布时间】:2018-09-23 14:23:05
【问题描述】:
我正在从 gulp 迁移到 webpack 设置。我希望 webpack 处理我的 js 和 css 资产并将它们打包成包。我设置了 2 个 webpack 配置文件:一个用于 js,一个用于 css。
我的项目中的 css 和 js 资产的总大小相似:每个部分大约 70 个文件(最小化 400kb)。
与 js 相比,我的问题与处理 css 资产时 webpack 性能差有关。
比较:
- JS 构建(首次运行):15-30 秒
JS 构建(带缓存):2 秒
CSS 构建(首次运行):15 秒
-
CSS 构建(带缓存):10 秒
显然,CSS 构建器使用缓存的效率不如 CSS 部分。老实说,我认为它根本不使用缓存(node_modules/.cache 没有任何相关内容),第二次运行更快的唯一原因是文件系统预热。
手表模式的问题更大。我做了一个测试,我在监视模式下运行 webpack 并修改了一个小文件(只有几行),它必须包含在一个更大的包中:
JS 更新:150 毫秒
- CSS 更新时间:1200-2000 毫秒
CSS builder 在这里表现不佳。此外,捆绑包越大,更新它们所需的时间就越长,即使更改是在一个应该立即编译的小文件中完成的。
此外,增加入口点的数量似乎也会对更新时间产生负面影响。更多条目 = 更新速度较慢,即使更新只影响一个小文件。
我尝试过使用cache-loader 并将其放置在提取插件之前和之后。老实说,帮助不大。当缓存加载器放在提取插件前面时,在监视模式下不会发出 css(仅 js 文件)。在提取器之后放置缓存加载器会稍微改进生产构建,但会减慢监视模式更新。
我目前的猜测是 sass 加载器不使用缓存,并且在每次模块更新时,整个包都必须从头开始编译并再次通过 sass > postcss > css > extract 管道。我想知道将导入管理委托给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;
【问题讨论】:
标签: javascript node.js webpack