可怕的启动时间
公司产品是一个比较大的后台管理系统如何优化网站的稳定程序,但是使用了webpack3的vue模板项目,单个项目启动时间达到70s左右
启动一个项目吃一碗腐竹脑就够了,但是没有腐竹脑怎么办,那就优化启动时间吧!
考虑到升级webpack版本的风险还是比较高的,有什么问题就得来找我。 想了想,不要冒险,注重安全,所以我选择通过插件来优化构建时间。
通过查阅资料,提高webpack的建立时间有几个方向:
根据上述优化方向,给出以下优化方案。
happypack的作用是将文件解析任务分解为多个子进程并发执行。
子进程处理完任务后,将结果发送给主进程。 因此,可以大大提高Webpack的项目预制组件的速度。
查看happypack的github,发现作者不再维护插件了,但是作者推荐使用webpack官方的多进程插件thread-loader,所以我放弃了happypacy,选择了thread-loader。
线程加载器
thread-loader 是一个官方维护的多进程加载器。 其功能与happypack类似。 它还通过启用子任务并行解析文件,从而提高构建速率。
将此装载机放在其他装载机后面。 然而,装载机是有限的。 例子:
每个worker都是一个独立的node.js进程,开销约为600纳秒。 还有进程间通信的开销。 在大型项目中使用Thread-Loader可能不会优化项目的构建速度,反而会减慢构建速度。 因此,在使用该装载机时,有必要了解项目施工形成的真实过程。
在我的项目中,我主要使用这个loader来解析vue和js文件,它工作在vue-loader和babel-loader上,如下:
const threadLoader = {
loader: 'thread-loader',
options: {
workers: require('os').cpus().length - 1,
}
}
module.exports = {
module:{
rules: [
{
test: /.vue$/,
use: [
threadLoader, // vue-loader前使用该loader
{
loader: 'vue-loader',
options: vueLoaderConfig
}
],
},
{
test: /.js$/,
use: [
threadLoader, // babel-loader前使用该loader
{
loader: 'babel-loader',
options: {
cacheDirectory: true
}
}
]
}
]
}
}
配置线程加载器后,尝试再次构建它。 如右图所示,设置时间缩短了10秒左右,还不错。
借助缓存提高二次建立的速度
虽然使用多进程构建项目将构建时间缩短了10秒,而且一分钟的构建时间仍然让人无法接受,但这些牙刷般的优化方法还是有些不舒服。 有没有更好的方法可以进一步减少呢? 构建时间短怎么样?
答案是肯定的,使用缓存。
缓存,不难理解,第一次创建的时候就缓存了创建的结果。 第二次创建时,检查对应的缓存是否发生变化。 如果没有变化如何优化网站的稳定程序,则直接使用缓存。 由此,我们可以想象,当项目变化较小时,大部分缓存是可以复用的。 获得完美的速度岂不是质的飞跃吗?
缓存加载器
说到缓存,其实百度一搜,第一个出现的就是cache-loader。 GitHub上搜索官方文档,得到如下结果:
这个加载器会缓存其他加载器的处理结果,并将这个加载器放在其他加载器的后面。 同时这个加载器也会有保存和读取缓存文件的开销,所以建议在开销较大的加载器之前使用这个加载器。
该文件非常简单。 考虑到项目中的vue-loader、babel-loader、css-loader会有比较大的开销,所以给这个loader添加一个缓存,然后将cache-loader添加到项目中:
const cacheLoader = {
loader: 'cache-loader'
}
const threadLoader = {
loader: 'thread-loader',
options: {
workers: require('os').cpus().length - 1,
}
}
module.exports = {
module:{
rules: [
{
test: /.vue$/,
use: [
cacheLoader,
threadLoader, // vue-loader前使用该loader
{
loader: 'vue-loader',
options: vueLoaderConfig
}
],
},
{
test: /.js$/,
use: [
cacheLoader,
threadLoader, // babel-loader前使用该loader
{
loader: 'babel-loader',
options: {
cacheDirectory: true
}
}
]
}
]
}
}
在util.js文件中,该文件主要是生成css相关的webpack配置,找到generateLoaders函数,修改如下:
const cacheLoader = {
loader: 'cache-loader'
}
function generateLoaders(loader, loaderOptions) {
// 在css-loader前增加cache-loader
const loaders = options.usePostCSS ? [cacheLoader, cssLoader, postcssLoader] : [cacheLoader, cssLoader]
if (loader) {
loaders.push({
loader: loader + '-loader',
options: Object.assign({}, loaderOptions, {
sourceMap: options.sourceMap
})
})
}
// Extract CSS when that option is specified
// (which is the case during production build)
if (options.extract) {
return ExtractTextPlugin.extract({
use: loaders,
fallback: 'vue-style-loader',
// 添加这句配置解决element-ui的图标路径问题
publicPath: '../../'
})
} else {
return ['vue-style-loader'].concat(loaders)
}
}
上述配置完成后,再次启动项目,可以发现当前启动时间没有太大变化。 我们第二次启动项目后,可以发现当前启动时间已经来到了30s左右。 上面我们已经说了,cache-loader缓存只有在第二次启动时才会生效。
虽然项目启动时间已经优化了一大半,而且我们的愿望是无限的,但是30秒的时间距离我们的预期还是有点远,继续优化!
硬源 webpack 插件
HardSourceWebpackPlugin 是一个 webpack 插件,为模块提供中间缓存步骤。 为了查看结果,您需要使用此插件运行 webpack 两次:第一次构建将花费正常的时间。 二期建设将大幅推进。
话不多说,直接配置到项目中:
const HardSourceWebpackPlugin = require('hard-source-webpack-plugin');
module.exports = {
//...
plugins: [
new HardSourceWebpackPlugin()
]
}
在第二次构建的时候,我们会发现构建时间已经到了个位数,只有短短的7秒。
在第二次构建的时候,我发现了一个现象,构建的进度会从10%跳到80%,甚至中间的构建过程也瞬间完成。 这证实了该插件为模块提供中间缓存的说法。
为模块提供中间缓存,我的理解是cache-loader缓存对应loader的处理结果,而这个插件甚至可以缓存整个项目的所有处理结果,直接引用最终输出的缓存文件,从而大大提高构建速度。
其他优化方法 babel-loader 启用缓存
Babel-loader有自己的缓存功能,只需启用cacheDirectory配置项即可。 根据官网介绍,启用缓存会使转换时间增加约两倍。
module.exports = {
module: {
rules: [
{
test: /.js$/,
use: [
...
{
loader: 'babel-loader',
options: {
cacheDirectory: true // 开启缓存
}
}
]
}
]
}
}
uglifyjs-webpack-plugin 支持多进程压缩
uglifyjs-webpack-plugin或者其他代码压缩工具提供了多进程压缩代码的功能,可以加快代码压缩速度。
动态填充
推荐查看这篇文章
一篇文章认识后端polyfill
总结
至此,我们完成了项目创建时间从70秒优化到7秒的优化过程。 在本文中,我们主要使用:
优化治疗效果的工具功能
线程加载器
多进程解析文件
70年代->60年代
缓存加载器
缓存一些高成本的加载器
60秒->30秒
硬源 webpack 插件
缓存模块中间过程
30秒->7秒
该项目逐步优化,几乎可以立即启动。 哎,看来抓鱼的时间少了,咱们努力打工吧!