南宁购物网站建设,建设银行车贷网站,做电影网站有什么好处和坏处,台州小型网站建设高级配置就是要进行 webpack 优化#xff0c;让代码在编译、运行时性能更好 主要从以下角度去优化#xff1a; 1、提升开发体验 2、提升打包构建速度 3、减少代码体积 4、优化代码运行性能 一、提升体验
1、SourceMap
为什么
打包出来的所有css和js合并成了一个文件#… 高级配置就是要进行 webpack 优化让代码在编译、运行时性能更好 主要从以下角度去优化 1、提升开发体验 2、提升打包构建速度 3、减少代码体积 4、优化代码运行性能 一、提升体验
1、SourceMap
为什么
打包出来的所有css和js合并成了一个文件将代码进行了编译、压缩多了其他代码。这种情况下进行 debug 是比较困难的因为看到的代码不仅是一坨有的较原代码还做了编译如剪头函数转换为了普通函数。
是什么
SourceMap源代码映射是一个用来生成源代码和构建代码一一映射的文件的方案。
SourceMap 会在dist目录生成一个 XX.map 文件里面包含源代码和构建后的代码没一行、每一列的映射关系。当代码报错时会通过 XXX.map 文件从构建后代码出错的位置找到映射后源代码的出错位置从而让浏览器提示源代码文件出错的位置帮助我们更快的找到错误根源。
怎么用
//webpack.dev.js 开发模式下
//优点打包编译速度快只包含行映射
//缺点没有列映射
// 其他省略
module.exports {mode: development,devtool: cheap-module-source-map,
};//webpack.prod.js 生产模式下
//优点包含行/列映射
//缺点打包编译速度更慢
module.exports {// 其他省略mode: production,devtool: source-map,
};说明
1、使用SourceMap会在打包输出目录的对应位置生产 XX.map 文件 2、css、js 都会生产 .map 文件 3、使用 SourceMap 后在浏览器控制台的 Sources 功能区可以通过 Commandp 搜索对应的文件 如main.js、main.css
二、提升打包构建速度
1、HotModuleReplacementHMR/热模块替换
是什么
HotModuleReplacementHMR/热模块替换在程序运行中替换、添加或删除模块无需重新加载整个页面刷新页面。
只需要在开发环境上配置生产环境不需要。
怎么用
css
devServer.hot 在webpack5时时默认开启的
module.exports {//开发服务器不会输出资源在内存中编译打包devServer: {host: 127.0.0.1,//启动服务器域名open: true, //启动服务器端口号port: 8000, //是否自动打开浏览器hot: true, // 开启HMR功能只能用于开发环境生产环境不需要了},
};js
HotModuleReplacement 只适用与cssjs修改还是会重新加载整个页面。要使js实现该功能需要在 main.js 增加
// main.js
// 判断是否支持HMR功能
if (module.hot) {module.hot.accept(./js/count.js, function (count) {//js更新后的回调const result1 count(2, 1);console.log(result1);});module.hot.accept(./js/sum.js, function (sum) {//js更新后的回调const result2 sum(1, 2, 3, 4);console.log(result2);});
}以上修改比较麻烦实际开发中也可以使用其他 loader 来解决如vue-loaderreact-hot-loader。
2、OneOf
为什么
打包时每个文件都会经过所有的loader处理虽然因为test正在原因实际上没有处理但是都要比对一遍比较慢。
是什么
只要匹配上一个 loader剩下的就不进行匹配。
怎么用
module.exports {module: {rules: [{oneOf: [{test: /\.css$/i, //使用正则匹配.css后缀的文件//执行顺序从右到左从上到下use:[style-loader, //将js中的css通过创建style标签的方式添加到html中css-loader //将css资源编译成commonjs的模块到js中]},{test: /\.less$/,use: [style-loader,css-loader,less-loader //将less编译成css文件]},]}]}
}3、Include/Exclude
为什么
开发时的第三方库或插件不需要再进行编译可以直接使用所以在对js文件处理时要做排除。
是什么
include 包含只处理XXX文件exclude 排除除了XX文件外其他文件都处理
怎么用
可以使用在loader里面也可使用在 plugin 中使用方法是一样的
//webpack.X.js
//loader修改
{test: /\.js$/,// exclude: /node_modules/, // 排除node_modules代码不编译include: path.resolve(__dirname, ../src), // 也可以用包含loader: babel-loader,// options: {// presets: [babel/preset-env]// }}4、cache
为什么
每次打包时js文件都要经过Eslint检查和Babel编译速度比较慢。 可以缓存之前的Eslint检查和Babel编译结果这样第二次打包的速度就是更快了。
是什么
对Eslint检查和Babel编译结果进行缓存缓存目录在 node_modules/.cache 下
怎么用
//webpack.XXX.js开发环境、生产环境都可以使用
//module.rules 下的loader
{test: /\.js$/,// exclude: /node_modules/, // 排除node_modules代码不编译include: path.resolve(__dirname, ../src), // 也可以用包含loader: babel-loader,options: {// presets: [babel/preset-env],cacheDirectory: true,//开启Babel编译缓存cacheCompression: false,//缓存文件不要压缩这里缓存是缓存在本地的}}plugins: [new ESLintWebpackPlugin({// 指定检查文件的根目录context: path.resolve(__dirname, ../src),exclude: node_modules, // 默认值cache: true, // 开启缓存// 缓存目录cacheLocation: path.resolve(__dirname,../node_modules/.cache/.eslintcache),})
],5、Thead 多进程
为什么
当项目越来约庞大打包速度会越来越慢。想要提升打包速度其实就是提升js的打包速度因为其他文件比较少。 对js文件处理主要是 eslint、babel、Terser 三个工具所以要提升他们的运行速度。 可以开启多个进程同事处理js文件。
是什么
多进程打包开启电脑的多个进程同事干一件事速度较快。 注意请仅在特别耗时的操作中使用因为每个进程启动就有大概600ms左右的开销。
怎么用
启动经常的数据就是cup的核数 1、下载包
$ npm i thread-loader -D2、获取cpu的核数每个电脑都不一样
// nodejs核心模块直接使用
const os require(os)
//cpu核数
const threads os.cpus().length3、js 使用
//webpack.xxx.js 中js-loader修改如下
{test: /\.js$/,// exclude: /node_modules/, // 排除node_modules代码不编译include: path.resolve(__dirname, ../src), // 也可以用包含use: [{loader: thread-loader,options: {workers: threads,}},{loader: babel-loader,options: {// presets: [babel/preset-env],cacheDirectory: true,//开启Babel编译缓存cacheCompression: false,//缓存文件不要压缩这里缓存是缓存在本地的}}]}4、css 使用
//webpack.xxx.js 中js-loader修改如下const TerserPlugin require(terser-webpack-plugin)//css增加进程可以写到 plugin 下面也可以写到 optimization 下面效果一样webpack5推荐写到 optimization 中
plugins: [//plugin的配置//将css输出到指定目录// new CssMinimizerPlugin(), //压缩css文件// new TerserPlugin({// parallel: threads// })
],
optimization: {minimize: true,minimizer: [//css压缩不仅可以写到plugin中也可写到optimization。minimizer中官方推荐就是这里效果一样new CssMinimizerPlugin(), //压缩css文件//生产模式会默认开启TerserPlugin这里需要进行其他配置就需要重新写new TerserPlugin({parallel: threads, //开启多进程})]},三、减少代码体积
1、Tree Shaking
为什么
开发时定义的一些工具函数或者饮用的第三方工具函数或组件库如果没有特殊处理打包时会引入整个库但是实际上我们可能只用了极小部分的功能这样整个库都打包进来体积会很大。
是什么
Tree Shaking是一个属术语通常用与描述一处 Javascript 中没有使用上的代码。 注它依赖 ES Module。
怎么用
Webpack 已经默认开启了这个功能无需其他配置。
2、Babel
为什么
Babel 为编译的每个文件都插入了辅助的代码是代码体积过大。 Babel 对一些公共方法使用了非常小的辅助代码比如_extend。默认情况下会被添加到每一个需要它的文件中。
是什么
babel/plugin-transform-runtime禁用了 Babel 自动对每个文件的 runtime 注入而是饮用babel/plugin-transform-runtime并且使所有辅助代码从这里引用。
怎么用
js loader中增加 plugins: [babel/plugin-transform-runtime]
//webpack.prod.js
{test: /\.js$/,// exclude: /node_modules/, // 排除node_modules代码不编译include: path.resolve(__dirname, ../src), // 也可以用包含use: [{loader: thread-loader,options: {workers: threads,}},{loader: babel-loader,options: {// presets: [babel/preset-env],cacheDirectory: true,//开启Babel编译缓存cacheCompression: false,//缓存文件不要压缩这里缓存是缓存在本地的plugins: [babel/plugin-transform-runtime], // 减少代码体积}}]
}3、Image Minimizer
为什么
如果项目中引用了较多图片那么图片体积会比较大将来请求速度比较慢。 开发可以对图片进行压缩减少图片体积。 注意如果项目中图片都是在线链接那么就不需要了。本地项目静态图片才需要进行压缩。
是什么
image-minimizer-webpack-plugin用来压缩图片的插件
怎么用
1、下载包
$ npm i image-minimizer-webpack-plugin imagemin -D还有剩下的包需要下载分两种模式
无损压缩
$ npm install imagemin-gifsicle imagemin-jpegtran imagemin-optipng imagemin-svgo -D有损压缩
$ npm install imagemin-gifsicle imagemin-mozjpeg imagemin-pngquant imagemin-svgo -D2、配置
//引入
const ImageMinimizerPlugin require(image-minimizer-webpack-plugin);
//------------------------optimization: {minimizer: [// 压缩图片new ImageMinimizerPlugin({minimizer: {implementation: ImageMinimizerPlugin.imageminGenerate,options: {plugins: [[gifsicle, { interlaced: true }],[jpegtran, { progressive: true }],[optipng, { optimizationLevel: 5 }],[svgo,{plugins: [preset-default,prefixIds,{name: sortAttrs,params: {xmlnsOrder: alphabetical,},},],},],],},},}),],四、优化代码运行性能
1、Code Split
为什么
打包代码时会将所有的 js 文件打包到一个文件中体积太大了。如果只要渲染首页就应该只加载首页的 js 文件其他文件不应该加载。
所以需要将打包生产的文件进行代码分割生成多个 js 文件渲染哪个页面就只加载某个 js 文件这样加载的资源少了速度就更快。
是什么
代码分割Code Split主要做了两件事 1、分割文件将打包生产的文件进行分割生产多个 js 文件 2、按需加载需要哪个文件就加载哪个文件
怎么用
1、创建一个新的目录目录结构如下其中 src 是多入口文件
2、初始化webpack项目下载包
$ npm init -y
$ npm i webpack webpack-cli html-webpack-plugin -D3、安装目录结构新建文件src中的随便写点东西主要是 webpack.cofig.js 的配置
//webpack.config.js
const path require(path)
const HtmlWebpackPlugin require(html-webpack-plugin)module.exports {// enrty: ./src/main.js, //只有一个入口文件单入口时使用这种方式entry: {//有多个入口文件多入口时 entry 要使用对象//对象包含输出的文件名入口文件路径app: ./src/app.js,main: ./src/main.js,},output: {path: path.resolve(__dirname, dist),filename: js/[name].js //webpack命名方式【name】是enrty中的键名},plugins: [new HtmlWebpackPlugin({template: path.resolve(__dirname, public/index.html)})],mode: production
}4、运行
$ npx webpack2、Code Split 提取重复代码
如果多入口文件都引用了同一份代码我们不希望这份代码被打包到两个文件中导致代码重复体积更大。 我们需要提取多入口文件的重复代码只打包生产一个 js 文件其他文件引用它就好。
//webpack.config.js
optimization: {// 代码分割配置splitChunks: {chunks: all, // 对所有模块都进行分割// 以下是默认值// minSize: 20000, // 分割代码最小的大小// minRemainingSize: 0, // 类似于minSize最后确保提取的文件大小不能为0// minChunks: 1, // 至少被引用的次数满足条件才会代码分割// maxAsyncRequests: 30, // 按需加载时并行加载的文件的最大数量// maxInitialRequests: 30, // 入口js文件最大并行请求数量// enforceSizeThreshold: 50000, // 超过50kb一定会单独打包此时会忽略minRemainingSize、maxAsyncRequests、maxInitialRequests// cacheGroups: { // 组哪些模块要打包到一个组// defaultVendors: { // 组名// test: /[\\/]node_modules[\\/]/, // 需要打包到一起的模块// priority: -10, // 权重越大越高// reuseExistingChunk: true, // 如果当前 chunk 包含已从主 bundle 中拆分出的模块则它将被重用而不是生成新的模块// },// default: { // 其他没有写的配置会使用上面的默认值// minChunks: 2, // 这里的minChunks权重更大// priority: -20,// reuseExistingChunk: true,// },// },// 修改配置cacheGroups: {// 组哪些模块要打包到一个组// defaultVendors: { // 组名// test: /[\\/]node_modules[\\/]/, // 需要打包到一起的模块// priority: -10, // 权重越大越高// reuseExistingChunk: true, // 如果当前 chunk 包含已从主 bundle 中拆分出的模块则它将被重用而不是生成新的模块// },default: {// 其他没有写的配置会使用上面的默认值minSize: 0, // 我们定义的文件体积太小了所以要改打包的最小文件体积minChunks: 2,priority: -20,reuseExistingChunk: true,},},},3、Code Split 按需加载动态倒入
场景页面上有一个按钮点击按钮的时候加载执行的方法。 1、修改文件
main.js
import {sum} from ./math
// import count from ./count //普通方式引入方法
console.log(main);
console.log(sum(5,6));document.getElementById(btn).onclick function() {// console.log(count(2,3));import(./count.js).then(({count}) {console.log(按需加载了 count(1,2,3,4,5));})
}public/index.html
!DOCTYPE html
html langen
headmeta charsetUTF-8meta nameviewport contentwidthdevice-width, initial-scale1.0titlewebpack-more-entry/title
/head
body哈哈哈哈button idbtn点击按钮/button
/body
/html第 四 部分功能代码见链接: https://pan.baidu.com/s/15yzdHnrWIKdo5ixeRdnJcw?pwdhqtf 提取码: hqtf
4、Code Split 单入口
开发时我们可能是单页面应用SPA只有一个入口单入口。那么我们需要这样配置主要是optimization.splitChunks.chunks 配置项
//webpack.config.js
const path require(path)
const HtmlWebpackPlugin require(html-webpack-plugin)module.exports {entry: ./src/main.js, //只有一个入口文件单入口时使用这种方式// entry: {// //有多个入口文件多入口时 entry 要使用对象// //对象包含输出的文件名入口文件路径// app: ./src/app.js,// main: ./src/main.js,// },output: {path: path.resolve(__dirname, dist),filename: js/[name].js, //webpack命名方式【name】是enrty中的键名clean: true},plugins: [new HtmlWebpackPlugin({template: path.resolve(__dirname, ./public/index.html)})],mode: production,optimization: {// 代码分割配置splitChunks: {// 对所有模块都进行分割//(把 node-modules 相关代码打包成一个文件//把动态倒入配置打包成一个文件)chunks: all, },}
}5、给模块命名
之前打包出来的文件名都是webpack自动生成的字符串读起来不太友好。
动态引入时使用注释语句/* webpackChunkName: count */把名字写进去 方法
// main.js
import {sum} from ./math
// import count from ./count //普通方式引入方法
console.log(main);
console.log(sum(5,6));document.getElementById(btn).onclick function() {// console.log(count(2,3));// /* webpackChunkName: count */ webpack魔法命名以注释的方式写入import(/* webpackChunkName: count */./count.js).then(({count}) {console.log(按需加载了 count(1,2,3,4,5));})
}修改webpack的输出配置chunkFilename
{path: path.resolve(__dirname, dist),filename: js/[name].js, //webpack命名方式【name】是enrty中的键名chunkFilename: js/[name].js, //打包输出的其他文件名clean: true
},6、统一命名配置
文件输出配置项配置chunk名字以及图片字体等文件资源的名字统一格式的名字
output: {path: path.resolve(__dirname, dist),filename: js/[name].js, //webpack命名方式【name】是enrty中的键名chunkFilename: js/[name].chunk.js, //动态输出资源命名方式assetModuleFilename: media/[name].[hash][ext],//图片、字体等资源命名方式clean: true},css、图片等相关资源的loader中文件名配置项 generator 去掉 打包出来的文件如下
2、Preload/Prefetch
为什么
前面已经做了代码分割同时会使用 import 动态倒入语法来进行代码按需加载也叫懒加载比如路由懒加载就是这样实现的。 但是加载速度还不够好如是用户点击按钮才加载这个资源的如果资源体积很大那么用户会感到明显的卡顿效果。 Preload或Prefetch技术是在浏览器空闲的时间加载后续需要使用的资源。
是什么
Preload是告诉浏览器立即加载资源Prefetch是告诉浏览器在空闲时才开始加载资源
共同点
都只会加载资源并不执行都有缓存
区别
Preload加载优先级高Prefetch加载优先级低Preload只能加载当前页面需要使用的资源Prefetch可以加载当前页面资源也可以加载下一个页面需要使用的资源
总结
当前页面优先级高的资源用Preload加载下一个页面页面需要使用的资源用Prefetch加载
问题兼容性较差Preload相对于Prefetch兼容性好一点
怎么用
下载包
$ npm i vue/preload-webpack-plugin -Dwebpack.config.js 中配置
plugins: [new PreloadWebpackPlugin({// rel: preload,// as: scriptrel: prefetch})
],3、Core-js
为什么
在这之前使用的 babel 对 js 代码进行了兼容性处理其中使用 babel/preset-env 智能预设来处理兼容性问题它能将 ES5 的一些语法进行编译转换比如剪头函数、三点运算符等。但是如果是 async 函数promise 对象数组的一些方法includes等它无法处理。 所以此时 js 代码仍然存在兼容性问题一旦遇到低版本浏览器会直接报错。所以需要将 js 兼容性问题彻底解决。
是什么
core-js是专门用来做 ES6 以及以上 API 的polyfill。 polyfill翻译过来叫垫片、补丁。就是用社区上提供的一段代码让我们在不兼容某些新特性等浏览器上使用该新特性
怎么用
main.js
//1、引入core-js下的所以资源缺点打出的包会比较大
// import core-js
//2、按需引入缺点手动引入容易遗漏
// import core-js/es/promise
//3、自动按需引入方法仅需配置 babel.config.jsnew Promise(resolve {setTimeout(() {resolve(2)console.log(promise);}, 1000);
})
const arr [1,2,3,4,5]
console.log(arr.includes(1));babel.config.js
module.exports {// 智能预设能够编译ES6语法presets: [[babel/preset-env,// 按需加载core-js的polyfill{ useBuiltIns: usage, corejs: { version: 3.32.2, proposals: true } },],],
};4、PWA
为什么
开发 Web App 项目项目一旦处理网络离线情况就没发访问了。我们希望给项目提供离线体验。
是什么
渐进式网络应用程序progressive web application - PWA是一种可以提供类似于 native app原生应用程序体验的 Web App 的技术。 其中最重要的是在离现象offline时应用程序能够继续运行功能。 内部是通过 Service Woekers 技术实现的。
怎么用
下载包
$ npm i workbox-webpack-plugin -Dwebpack.config.js 中增加
//引入workbox-webpack-plugin
const WorkboxPlugin require(workbox-webpack-plugin);
//plugin中使用WorkboxPlugin
plugins: [new HtmlWebpackPlugin({template: path.resolve(__dirname, ./public/index.html)}),new PreloadWebpackPlugin({// rel: preload,// as: scriptrel: prefetch}),new WorkboxPlugin.GenerateSW({// 这些选项帮助快速启用 ServiceWorkers// 不允许遗留任何“旧的” ServiceWorkersclientsClaim: true,skipWaiting: true,}),
],main.js 增加判断 因为 serviceWorker 具有兼容性问题这里要加一下判断
if (serviceWorker in navigator) {window.addEventListener(load, () {navigator.serviceWorker.register(/service-worker.js).then((registration) {console.log(SW registered: , registration);}).catch((registrationError) {console.log(SW registration failed: , registrationError);});});
}重新打包打包出来的目录下多了service-worker.js和workbox-XXX.js 此时如果直接在浏览器中打开 dist/index.html将浏览器置为 offline控制台是会报错的找不到相关服务这时需要下载 serve
$ npm i serve -g之后执行启动命令 serve dist根据输出ip打开即可此时设置 offline 时刷新页面页面内容还是存在的。
总结 以上代码参考链接: https://pan.baidu.com/s/1Y9fcso1l-Cyt-eIGKSfqow?pwd9jh0 提取码: 9jh0