服务器webpack编译速度优化,webpack 性能优化

开发环境性能优化

优化打包构建速度

HMR优化代码调试source-map

生产环境性能优化

优化打包构建速度

oneOf babel 缓存 多进程打包 externals dll 优化代码运行的性能 缓存(hash,chunkhash,contenthash) tree shaking code split 懒加载和预加载 pwa

优化 开发环境 打包构建速度

HMR hot module replacement 热模块替换/模块热替换

作用:一个模块发生变化,只会重新打包这一个模块 而不是重新打包所有,极大提升构建速度

样式文件: 可以使用HMR功能,因为style-loader内部实现了 js文件: 默认不能使用HMR功能 -->解决:需要修改js代码,添加支持HMR功能的代码。注意,HMR功能对js的处理,只能处理非入口js文件的其他文件。

if(module.hot){

//一旦module.hot是true,说明开启HMR功能,让HMR功能代码生效

module.hot.accept('./xxx.js',function(){

//此方法会监听print.js文件的变化,一旦发生变化,其他默认不会重新打包构建

//会执行后面的回调函数

xxx();

})

}

html文件: 默认不能使用HMR功能,同时会导致问题:html文件不能热更新了 解决:改 entry:['入口js','html'] ,但html文件只有一个,所以不用做HMR功能

devServer:{

//项目构建后的目录

contentBase: resolve(__dirname,'build'),

//启用gzip压缩

compress:true,

//端口号

port:3000,

//自动打开浏览器

open:true

}

优化 开发环境 代码调试

source-map 一种提供源代码到构建后代码映射的技术

如果构建后代码出错了,通过映射可以追踪到错误的代码

webpack.config.js

devtools:'source-map'

//其他 参数 [inline-|hidden-|eval-][nosources-][cheap-[module-]]source-map

source-map : 外部

错误代码的准确信息和错误位置

inline-source-map : 内联

错误代码的准确信息和错误位置

hidden-source-map : 外部

错误代码的错误原因 但没有错误位置,不能追踪到源代码的错误,只能提示到构建后代码的位置

eval-source-map : 内联

每一个文件都生成对应的source-map,都在eval

错误代码的准确信息和错误位置

nosources-source-map : 外部

能找到错误代码的准确信息 但没有任何源代码信息

cheap-source-map : 外部

错误代码的准确信息和错误位置 只精确到行,不精确到列

cheap-module-source-map : 外部

错误代码的准确信息和错误位置

module 会将 loader 的 source-map加入

内联 和 外部的区别 :

1.外部生成了文件但内联没有生成

2.内联构建速度更快

开发环境:速度快,调试更友好

速度快 eval>inline>cheap>...

调试更友好 souce-map>cheap-module-souce-map>cheap-souce-map

所以 一般用eval-source-map

生产环境:源代码要不要隐藏,调试要不要友好?内联会让体积编码,所以一般不用内联

nosources-source-map 隐藏源代码

hidden-source-map 只隐藏源代码,会提示构建购代码错误信息

--> source-map /cheap-module-souce-map

优化生产环境

oneOf

rules里中有许多个loader,这样会导致每个文件都会被所有的loader过一遍,有些能处理,有些处理不了。所以可以利用oneOf达到以下loader只会匹配到第一个。但需要注意,不能有两个loader同时处理同一个文件

webpack.config

module.exports={

//....

module:{

rule:[

//正常来讲,一个文件只能被一个loader处理

//当一个文件要被多个loader处理,那么一定要指定loader的执行顺序

// 先执行eslint 再执行babel

{

test:/\.js$/,

exclude:/node_modules/,

//优先执行

enforce:'pre',

loader:'eslint-loader',

options:{

fix:true

}

},

{

oneOf:[

{

test: /\.css$/,

use:[

...commonCssLoader

]

},

{

test:/\.less$/,

use:[

...commonCssLoader,'less-loader'

]

},

{

test:/\.js$/,

exclude:/node_modules/,

loader:'babel-loader',

options:{

// 预设 :指示babel做怎样的兼容性处理

presets:[

[

'@babel/preset-env',

{

//按需加载

useBuiltIns:'usage',

//指定core-js版本

corejs:{

version:3

},

//指定兼容性做到哪个版本的浏览器

targerts:{

chrome: '40',

fixfox: '50',

ie: '9',

safari: '10',

edge: '17'

}

}

]

]

}

},

{

test:/\.(png|jpg|gif)/,

loader:'url-loader',

enModule:true,

options:{

limit:8*1024,

name:'[hash:10].[ext]',

outputpath:''

}

},

{

test:/\.html$/,

loader:'html-loader'

},

{

exclude:/\.(js|less|css|png|jpg|gif)/,

loader:'file-loader',

options:{

name:'[hash:10].[ext]'

}

}

]

}

]

},

}

缓存

1.babel缓存-->第二次打包更快

{

test:/\.js$/,

exclude:/node_modules/,

loader:'babel-loader',

options:{

// 预设 :指示babel做怎样的兼容性处理

presets:[

[

'@babel/preset-env',

{

//按需加载

useBuiltIns:'usage',

//指定core-js版本

corejs:{

version:3

},

//指定兼容性做到哪个版本的浏览器

targerts:{

chrome: '40',

fixfox: '50',

ie: '9',

safari: '10',

edge: '17'

}

}

]

],

//第二次构建时,会读取之前的缓存

cacheDirectory: true

}

},

2.文件资源缓存-->上线缓存优化

hash:每次webpack构建会生成一个唯一hash值

问题: 因为js和css同时使用一个hash值,如果重新打包,会导致所有缓存失效,可能我却只改了一个文件,

chunkhash:根据chunk生成hash值,如果打包来源于同一个chunk,那么hash值也一样

问题:js和css的hash值还是一样的。

原因:css是由js引入的,所以属于同一个chunk

contenthash: 根据文件内容生成hash值,

webpack.config.js

tree shaking

去除应用程序中没有使用的代码

前提:

1.必须使用es6模块化

2.开启production模式

在package.json中配置

"sideEffects":false所有代码都没有副作用,都可以镜像tree sharking

问题 可能会把css/@babel/polyfille 干掉

"sideEffects": ["*.css","*.less"] 哪些文件不 tree sharking

code split

1.入口配置

单入口 //单页面应用

entry:'./src/js/index.js'

多入口 //多页面应用

entry:{

index:'./src/js/index.js',

test:'./src/js/test.js'

}

2.optimization

module.exports={

//...

// 可以将nodemudules中的代码单独打包成一个chunk最终输出

// 还可以自动分析多入口chunk中,有没有公共的文件,如果有会打包成一个单独的chunk

optimization:{

splitChunks:{

chunks:'all'

}

}

}

3.import 动态导入语法,能将某个文件单独打包

通过js代码,让某个文件被单独打包成一个chunk,通过注释可以固定此文件的名称

import(/*webpackChunkName:'xxxName'*/'./xx/xxx.js')

.then(res =>{

//加载成功

})

.catch(()=>{

//加载失败

})

懒加载和预加载

1.懒加载 当文件需要用时才加载

import 动态导入语法

document.getElementById('btn').onclick =function(){

import(/*webpackChunkName: 'xxxName'*/'./xx/ss.js')

.then(res=>{

//干啥干啥

})

}

2.预加载 webpackPrefetch:true

./xx/ss.js 已经被加载了,点击的时候再从缓存中加载,

document.getElementById('btn').onclick =function(){

import(/*webpackChunkName: 'xxxName',webpackPrefetch:true*/'./xx/ss.js')

.then(res=>{

//干啥干啥

})

}

正常加载可以认为是并行加载(同一时间加载多个文件) 预加载prefectch 等其他资源加载完毕,浏览器空闲了,再偷偷加载资源 兼容性比较差 慎用

PWA 渐进式网络开发应用程序

网络离线可访问

webbox-->webbox-webpack-plugin

const WebboxWebpackPlugin = require('webbox-webpack-plugin')

module.exports={

plugins:[

new WebboxWebpackPlugin.GenerateSW({

/*

1.帮助 serviceWorker 快速启动

2.删除旧的 serviceWorker

生成一个 serviceWorker 配置文件

*/

clientsClaim:true,

skipWaiting:true

})

]

}

index.js 中注册serviceworker

//处理兼容性

if('serviceWorker'innavigator){

window.addEventListener('load',()=>{

navigator.serviceWorker

.register('./service-work.js')

.then(()=>{

//成功

})

.catch(()=>{

//失败

})

})

}

1.可能会出现问题 eslint不认识window和navigator

解决 package.json中eslintConfig中配置

"env":{

"browser":true//支持浏览器端的变量

}

2. sw代码必须运行在服务器上

-->node.js

--> npm i serve -g

serve -s build 启动一个服务器将build下的资源作为静态资源暴露出去

多进程打包

thread-loader 一般给babel-loader用

但需要注意

进程启动大约需500ms,进程间通信也有开销。只有工作消耗时间比较长,才需要多进程打包

{

test:/\.js$/,

exclude:/node_modules/,

use:[

//'thread-loader',

{

loader:'thread-loader',

options:{

workers: 2 //进程2个

}

}

{

loader:'babel-loader',

options:{

// 预设 :指示babel做怎样的兼容性处理

presets:[

[

'@babel/preset-env',

{

//按需加载

useBuiltIns:'usage',

//指定core-js版本

corejs:{

version:3

},

//指定兼容性做到哪个版本的浏览器

targerts:{

chrome: '40',

fixfox: '50',

ie: '9',

safari: '10',

edge: '17'

}

}

]

],

//第二次构建时,会读取之前的缓存

cacheDirectory: true

}

}

]

},

externals

module.exports={

externals:{

//忽略/拒绝  库名 -- npm 包名

//可以在index.html中引入cdn

}

}

dll 动态连接

使用dll技术 对某些库(第三方库) 进行单独打包

指令 webpack--config webpack.dll.js

webpack.dll.js

const {resolve} = require('path')

const webpack = require('webpack')

module.exports = {

entry:{

//最终打包生成的[name]-->jquery

//['jquery']-->要打包的库是jquery

jquery:['jquery']

},

ouput:{

filename:'[name].js',

path:resolve(__dirname,'dll'),

library:'[name]_[hash]'//打包的库里面向外暴露出去的内容叫什么名字

},

plugin:[

new webpacl.DllPlugin({

//打包生成一个manifest.json --> 提供和jquery映射

name:'[name]_[hash]',//映射库的暴露内容名称

path:resolve(__dirname,'dll/manifest.json')

})

],

mode:'production'

}

webpack.config.js

const AddAssetHtmlWebpackPlugin = require('add-asset-html-webpack-plugin')

module.exports={

plugins:[

//告诉webpack哪些库不参与打包,同时名称也得变

new webpack.DllReferencePlugin({

manifest: resolve(__dirname,'dll/manifest.json')

}),

//将某个文件打包输出出去,并在html中引入该资源

new AddAssetHtmlWebpackPlugin({

filepath:resolve(__dirname,'dll/jquery.js')

})

]

}

编辑推荐

【责任编辑:姜华 TEL:(010)68476606】

点赞 0

你可能感兴趣的:(服务器webpack编译速度优化,webpack 性能优化)