首页IT科技webpack优化前端性能(webpack性能优化方案)

webpack优化前端性能(webpack性能优化方案)

时间2025-10-06 05:09:51分类IT科技浏览6815
导读:webpack性能优化从两个方向来考虑:优化打包速度和优化打包文件大小。...

webpack性能优化从两个方向来考虑:优化打包速度和优化打包文件大小                。

一, 优化打包速度

1.webpack区分环境配置文件                ,避免加载多余的插件                        。

2.对 webpack 的 resolve 参数进行合理配置                        ,减少查找过程        。

webpack的resolve常用配置如下        。

resolve: {

//extensions表示的是可省略的文件拓展名        ,参数是一个数组

extensions: [.js, .jsx],

//alias 的意思为 别名        ,能把原导入路径映射成一个新的导入路径                        ,减少查找过程                        。将 resolve.alias 设置为 false 将告知 webpack 忽略模块                。

alias: {

alias: path.resolve(__dirname, ../src/alias),

},

//modules的配置是优化配置                ,告诉webpack去什么目录下查找node_modules文件夹

modules: [

path.resolve(__dirname, node_modules), // 指定当前目录下的 node_modules 优先查找 node_modules, // 将默认写法放在后面

]

}

3.缩小构建目标        ,排除 Webpack 不需要解析的模块        。即使用 loader 的时候                        ,在尽量少的模块中去使用                        。我们可以借助 include 和 exclude 这两个参数                ,规定 loader 只在那些模块应用和在哪些模块不应用                。

module: {

rules: [

{

test: /.js|jsx$/, exclude: /node_modules/, // 排除模块 include: path.resolve(__dirname, ../src), //要应用的模块 use: [babel-loader]

},

// ...

]

}

4>利用多线程提升构建速度。多线程常用插件有HappyPack和thread-loader,HappyPack 的作者现在基本上不维护这个插件了                        ,所以我们可以用thread-loader配置多线程                        。

使用方式如下:

module: {

rules: [{

test: /.jsx?$/, exclude: /node_modules/, // include: path.resolve(__dirname, ../src), use: [ { loader: thread-loader, options: { workers: 3, // 开启几个 worker 进程来处理打包                        ,默认是 os.cpus().length - 1 } }, babel-loader ]

}]

}

5.预先编译资源模块(DllPlugin)                        。

我们在打包的时候,一般来说第三方模块是不会变化的                ,所以我们想只要在第一次打包的时候去打包一下第三方模块                        ,并将第三方模块打包到一个特定的文件中        ,当第二次 webpack 进行打包的时候                ,就不需要去 node_modules 中去引入第三方模块                        ,而是直接使用我们第一次打包的第三方模块的文件就行。

// build/webpack.dll.js

const path = require(path);

const webpack = require(webpack);

module.exports = {

mode: production, // 环境

entry: {

vendors: [lodash], // 将 lodash 打包到 vendors.js 下

},

output: {

filename: [name].dll.js, // 输出的名字 path: path.resolve(__dirname, ../dll), // 输出的文件目录 library: [name] // 将我们打包出来的文件以全部变量的形式暴露        ,可以在浏览器变量的名字进行访问

},

plugins: [

// 对生成的库文件进行分析        ,生成库文件与业务文件的映射关系                        ,将结果放在 mainfest.json 文件中 new webpack.DllPlugin({ name: [name], // 和上面的 library 输出的名字要相同 path: path.resolve(__dirname, ../dll/[name].manifest.json), })

]

}

6.缓存 Cache 相关

(1)babel-loader开启缓存:

use: [

{

loader: babel-loader, options: { cacheDirectory: true, }

},

]

(2)在一些性能开销较大的 loader 之前添加 cache-loader                ,以便将结果缓存到磁盘里

module.exports = {

module: { rules: [ { test: /.ext$/, use: [cache-loader, ...loaders], include: path.resolve(src), }, ], },

};

7.合理使用 sourceMap

在开发环境        ,我们的要求是:快                        ,能够定位到源码的出错位置

所以一般来说选择:cheap-module-source-map

线上环境的话                ,我们是不能让使用者可以看到source-map的,所以使用hidden-source-map                        ,配合前端监控系统

source-map                        ,表示生成map文件

加上inline,表示生成map写在js里

加上cheap                ,表示生成map写在js里                        ,只映射行        ,不映射列                ,并且只映射业务代码                        ,不管引入的第三方模块

加上module        ,是管第三方模块的映射

加上eval        ,用eval执行来提示映射关系

开发推荐cheap-module-eval-source-map

线上推荐cheap-module-source-map

注意: webpack4.0+; webpack配置 devtool: "source-map" 生成的map代码没有 sourcesContent                        ,没有sourcesContent的结果是你只能定位要压缩代码的位置                ,无法定位到源码的位置                。正确配置如下:

const buildConfig = {

mode: "production",

output: { path: distPath, filename: "./js/[name].[hash].min.js", publicPath: "./" },

optimization: {

minimize: false// 1. 这个配置必须

},

plugins: [ ].concat(baseConfig.htmlArray),

devtool: "source-map" // 2. 这个配置必须 }

二. 优化文件体积

1. wepack区分环境配置文件                         。

建议把webpack.config.js文件拆分为webpack.common.js        ,webpack.dev.js和webpack.prod.js                        ,这样把类似HMR之类的开发环境用到的包去掉        。

2.js压缩

使用terser-webpack-plugin                 ,也可用 uglifyjs-webpack-plugin,两者的区别是后者对 ES6 的压缩不是很好                。

示例:

const TerserPlugin = require(terser-webpack-plugin);

webpack.common.js:

optimization: {

minimizer: [

new TerserPlugin({

parallel: 4, // 开启几个进程来处理压缩                        ,默认是 os.cpus().length - 1

}),

],

},

}

3.css压缩

使用css-minimizer-webpack-plugin

使用方式:const CssMinimizerPlugin=require("css-minimizer-webpack-plugin")

webpack.prod.js:

optimization: {

minimizer: [

new CssMinimizerPlugin()

]

}

4. 拆分代码(code Spliting)减少main.js包的体积

使用splitChunks选项

optimization: {

splitChunks:{//自动实现代码分割

chunks:all,//异步                 ”all" 对同步和异步都有效

minSize: 20000,

minRemainingSize: 0,

minChunks: 1,

maxAsyncRequests: 30,

maxInitialRequests: 30,

enforceSizeThreshold: 50000,

cacheGroups:{

vendors:{

test:/[\/]node_modules[\/]/, priority:-10, //优先级 数字越大                         ,优先级越高 filename:"vender.js" //对打包的文件名进行重置

},

default:{//所有代码分割快都符合默认值,此时判断priority优先级

minChunks:2, priority:-20 , reuseExistingChunk:true//允许在模块完全匹配时重用现有的块                ,而不是创建新的块                        。

}

}

}

}

5.去除不引用的代码(tree-shaking)

注意:tree-shaking 只在mode为production生效

需要手动开启:

webpack.config.js设置:

optimization:{

useExports:true

}

另外:package.json需要设置为false                        ,防止忽略 “import form ./index/css                        ” 之类的文件引用

"sideEffects":false,//所有的模块需要监控 .["*.css"] 排除css监控

6. "babel/preset-env"开启按需加载        。

babel的polyfill总是比较大        ,会影响一些性能                ,而且也会有一些没用的polyfill                        ,useBuiltIns的按需加载:usage        ,可减少polyfill的体积.

配置中设置useBuiltIns:usage        ,babel就会自动把所需的polyfill加载进来                        ,不需要手动import polyfill文件        。

useBuiltIns参数配置:"usage" | "entry" | false                ,默认值是 fals

false:需要在 js 代码第一行主动 import @babel/polyfill        ,会将@babel/polyfill 整个包全部导入                        。

(不推荐                        ,能覆盖到所有 API 的转译                ,但体积最大)

entry:需要在 js 代码第一行主动 import @babel/polyfill,会将 browserslist 环境不支持的所有垫片都导入                。

(能够覆盖到‘hello‘.includes(‘h‘)这种句法                        ,足够安全且代码体积不是特别大)

usage:项目里不用主动 import                        ,会自动将代码里已使用到的                、且 browserslist 环境不支持的垫片导入        。

(但是检测不到‘hello‘.includes(‘h‘)这种句法,对这类原型链上的句法问题不会做转译                ,书写代码需注意

提取文件:.babelrc

内容:

{

"presets":[

[

"@babel/preset-env",{ //兼容的浏览器版本(向上兼容) "targets":{ "edge":"17", "firefox":"60" // "Android":"6.0 }, //按需加载 "useBuiltIns":"usage", "corejs":2 }], //解析react "@babel/preset-react"

]

}

补充概念:

babel-loader 不是用来 ES6 转译的                        ,它充其量只是一个打通 babel 与 webpack 的一个 桥梁         ,首先两者得建立一个连接                        。

{} 转为 function () {} ES5函数                。

但是 @babel/preset-env 不会转换 新的API                ,以及一些在全局对象上的方法 都不会进行转码。 比如 Iterator, Generator, Set, Maps, Proxy, Reflect,Symbol,Promise 等全局对象                        ,以及 Object.assign         , Array.from 全局对象的方法        ,都不会进行转码                        。

polifill作用:

识别es6新增的对象                        ,如promise等

与@babel/polifill对比                ,@babel/plugin-transform-runtime 不会造成全局污染

但是 @babel/plugin-transform-runtime不会对Array.prototype.include() 进行polifill (原型链上的方法)

其他:配置webpack时需要注意的点

1>提取单独的css文件:css 代码引用默认打包在js里        ,不会单独抽离                        ,需要mini-css-extract-plugin插件协助处理

用法:const MinCssExtractPlugin=require("mini-css-extract-plugin")

将"style-loader         ”替换为MinCssExtractPlugin.loader                 ,并引入插件

plugins:[

new MinCssExtractPlugin({

filename:[name].[contenthash].css,

chunkFilename: [id].css

})]

2>将file-loader 替换为url-loader,可以对一定范围内的图片进行base64转换                        ,减少http请求

设置:

rules:[

{

test:/.(png|jepg|jpg|gif)$/,

use:{

//url-loader 可以限定模块的体积                        ,根据体积判断是否需要转换base64,减少http请求 loader:url-loader,//把模块放到另一个目录里 options:{ limit:10000, /*limit: 10000,限制 图片大小 10000b(10k)                ,小于限制会将图片转换为 base64格式*/ //name 是打包前的文件名称                        。hashhash值                        ,防止缓存。ext是打包前的文件格式 name:"[name].[hash].[ext]", outputPath:imgs/

}}

}]

3>使用最新版本的webpack        ,打包速度会更快                。

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
opencart官网(openai.error.AuthenticationError: No API key provided.)