webpack系列笔记(5)性能优化

本文介绍了webpack的性能优化方法,包括px转rem配置、静态资源内联、样式注入方式、html压缩、多页面应用打包策略、sourceMap的启用、公共资源提取、tree shaking和死代码消除、Scope Hoisting的原理及开启、懒加载与动态import的实现以及webpack与ESLint的结合使用。详细讲解了各种优化技术的实践步骤和应用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

移动端css px自动转换成rem:

px2rem-loader:

{ 

loader: 'px2rem-loader', 

options: { 

remUnit: 75, 

// 1个rem是多少px, 一般以750设计稿,

vw/10是75 remPrecision: 8 

// rem计算保留8个小数点 

} }

 

静态资源内联:

css内联:

方法一:借助style-loader:

{ loader: 'style-loader', options: { insert: 'top',

// 样式插入到<head>

injectType: 'singletonStyleTag',

// 将所有的style标签合并成一个 } } }

 

方法二:html-inline-css-webpack-plugin:

将<link rel="stylesheet" /> => <style>...<style/>

const HTMLInlineCSSWebpackPlugin = require('html-inline-css-webpack-plugin').default; ... plugins: [ new HTMLInlineCSSWebpackPlugin() ]

 

raw-loader: 只能安装0.5.1版本,否则会报错

 

html-webpack-plugin: html压缩的plugin.可以自动创建html模板组件,默认支持html、ejs, 其他模板引擎需要相关加载器。

<!DOCTYPE html> <html lang="en"> <head> ${ require('raw-loader!./meta.html') } <title>Document</title> <script>${ require('raw-loader!babel-loader!../node_modules/lib-flexible/flexible.js') }</script> </head> <body> <div id="root"></div> </body> </html>

 

多页面应用打包通用方案:

const glob = require('glob'); 

const setMPA = () => { 

const entry = {}; 

const htmlWebpackPlugin = []; 

const entryFiles = glob.sync(path.join(__dirname, './src/*/index.js')); 

console.log('entryFiles', entryFiles); 

Object.keys(entryFiles) .map((index) => { 

const entryFile = entryFiles[index]; 

// '/Users/wangrui/workspace/tech/webpack-demos-jk/src/index/index.js' 

const match = entryFile.match(/src\/(.*)\/index\.js/); 

const pageName = match && match[1]; 

entry[pageName] = entryFile; 

htmlWebpackPlugin.push( new HtmlWebpackPlugin({ template: path.join(__dirname, `src/${pageName}/index.html`), filename: `${pageName}.html`, 

chunks: [pageName], inject: true, minify: { html5: true, collapseWhitespace: true, preserveLineBreaks: false, minifyCSS: true, minifyJS: true, removeComments: false } }), ); }) return { entry, htmlWebpackPlugin } } 

const { entry, htmlWebpackPlugin } = setMPA(); 

... 

plugins: [ 

new MiniCssExtractPlugin({ filename: `[name]_[contenthash:8].css` }), 

new OptimizeCSSAssetsPlugin({ assetNameRegExp: /\.css$/g, cssProcessor: require('cssnano') }), 

new CleanWebpackPlugin(), 

new HTMLInlineCSSWebpackPlugin() ].concat(htmlWebpackPlugin)

sourceMap:

参考文档:

http://www.ruanyifeng.com/blog/2013/01/javascript_source_map.html

如何启用sourceMap?

//@ sourceMappingURL=/path/to/file.js.map

 

sourceMap类型是:

eval, source-map, inline-source-map

 

提取公共资源:

1. html-webpack-external-plugin:

new HtmlWebpackExternalsPlugin({ externals: [ { module: 'react', entry: 'https://11.url.cn/now/lib/16.2.0/react.min.js', global: 'React', }, { module: 'react-dom', entry: 'https://11.url.cn/now/lib/16.2.0/react-dom.min.js', global: 'ReactDOM', }, ], })

2. splitchunks:

 

(1) 将react、react-dom这种大库抽离出来,单独打包

optimization: { splitChunks: { cacheGroups: { vendors: { test: /(react|react-dom)/, name: 'vendors', chunks: 'all', } } } },

 

<body> <div></div> <script type="text/javascript" src="https://11.url.cn/now/lib/16.2.0/react.min.js"></script> <script type="text/javascript" src="https://11.url.cn/now/lib/16.2.0/react-dom.min.js"></script> </body>

 

(2)将公共使用的方法抽离出来common, 单独打包js

optimization: { splitChunks: { minSize: 0, cacheGroups: { commons: { name: 'commons', chunks: 'all', minChunks: 2 } } } }

 

tree shaking: 摇树优化:

1个模块可能有多个方法,只要其中的某个方法用到了,则整个文件都会被打包到bundle里面去,tree shaking就是只把用到的方法打入bundle, 没用到的方法会在uglify阶段被擦除掉。

 

使用:webpack默认支持,在.babelrc里面设置modules:false即可。

production的mode下会默认开启。

要求:必须是ES6的语法,CJS的方式不支持

 

DCE: dead code elimination 死代码消除

代码不会被执行

代码执行的结果不会被用到

代码只会影响死变量(只写不读)

 

如果不开启tree shaking的话,(设置mode为none),那么一个js中的方法只引用了,但是并没有在代码里面使用,则会在打包后的bundle包里面搜到的。开启tree shaking(设置mode为production),那么打包出来的bundle包已经将这个没有用到的方法进行擦除

 

Scope Hoisting 使用和原理分析:

被webpack转换后的模块会带上一层包裹

import会被转换成_webpack_require,用来加载模块,返回module.exports.

_webapack_require__(0) 执行代码块

 

原理:将所有的模块的代码按照引用顺序放在一个函数作用域里面,然后适当的重命名一些变量以防止变量名冲突

对比:通过scope hoisting 可以减少函数声明代码和内存开销。

默认mode为production就会自动开启scope hoisting, 执行这个插件。

plugins: [ new webpack.optimize.ModuleConcatenationPlugin() ]

 

必须是ES6语法,CJS不支持。

 

代码分割和动态import:

懒加载JS脚本:

CommonJS: require.ensure

ES6:动态 import (目前还没有原生支持,需要babel转换)

 

如何使用动态import?

1. 安装babel插件:

npm install @babel/plugin-syntax-dynamic-import -D

 

2. ES6: 动态import (目前还没有原生支持,需要babel转换)

{ 'plugins': ['@babel/plugin-syntax-dynamic-import'] ... }

 

import('./test.js') 返回的是一个promise

 

webpack和ESLint结合:

一、开发阶段增加precommit钩子:

1. 安装husky:

npm i husky -D

 

2.增加npm script, 通过lint-staged增量检查修改的文件

在package.json文件中添加如下:

"husky": { "hooks": { "commit-msg": "validate-commit-msg" } }, "lint-staged": { "src/**/*.ts": [ "eslint --fix", "git add" ], "src/**/*.tsx": [ "eslint --fix", "git add" ] }

 

二、webpack与eslint集成:

使用eslint-loader,构建时检查JS规范:

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

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值