# vue-webpack5 **Repository Path**: pear66/vue-webpack5 ## Basic Information - **Project Name**: vue-webpack5 - **Description**: 该仓库主要用来搭建项目的框架,内部继承所有webpack的基础配置、高级配置对于想学习webpack配置的人来说,是个不错的选择 - **Primary Language**: JavaScript - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2025-03-27 - **Last Updated**: 2025-03-28 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # vue2_wepack_demo # 项目创建 ```bash npm install vue-cli -g vue create vue2_weback_demo ``` vue create 和vue init 两种创建方式的区别 1. vue create 是vue-cli3.x的初始化方式,目前模板是固定的,模板选项可自由配置,创建出来的是vue-cli3的项目,与cue-cli2项目结构不同,配置方法不同,具体配置方法参考官方文档。 使用方式:vue create 项目名称 2. vue init vue init 是vue-cli2.x的初始化方式,可以使用github上面的一些模板来初始化项目,webpack是官方推荐的标准模板名。vue-cli2.x项目向3.x迁移只需要把static目录复制到public目录下,老项目的src目录覆盖3.x的src目录(如果修改了配置,可以查看文档,用cli3的方法进行配置) webpack是官方推荐的标准模板名 使用方式:vue init webpack 项目名称 使用方式:vue init simulatedgreg/electron-vue 项目名称 ## Project setup ``` npm install ``` ### Compiles and hot-reloads for development ``` npm run serve ``` ### Compiles and minifies for production ``` npm run build ``` ### Lints and fixes files ``` npm run lint ``` ### Customize configuration See [Configuration Reference](https://cli.vuejs.org/config/). ## webpack配置 ```bash npm install webpack webpack-cli -D npm install webpack-dev-server -D ``` webpack.config.js 初始化配置是参考B栈视频学习整理的,有兴趣的小伙伴也可以看一下,话不多说,下面进入配置 [参考视频](https://www.bilibili.com/video/BV14T4y1z7sw?spm_id_from=333.788.player.switch&vd_source=c66164131f1b543261221c05bce65e2e&p=27) ### 初级配置 #### 1、配置入口和出口文件 - 知道要从哪个文件开始打包,从哪个目录输出 ```javascript module.exports = { // 也可以配置为一个数组,配置多入口 entry: './src/main.js', mode: "development", output: { path: path.resolve(__dirname, 'dist'), filename: 'bundle.js', }, } ``` #### 2、配置loader - 页面有各种语言,css、js、less等,要配置解析器让webpack打包的时候能够识别他,解析成浏览器识别的语法。 ```javascript // 用来处理获取的样式 function getStyleLoaders(pre) { return [MiniCssExtractPlugin.loader, "css-loader", { loader: "postcss-loader", options: { postcssOptions: { // plugins: [["autoprefixer"]], plugins: ['postcss-preset-env'],//能解决大多数兼容性问题 }, }, }, pre].filter(Boolean); } module: { rules: [ { test: /\.css$/,// 匹配的条件 use: [ // 通过style标签动态插入style标签 'style-loader', // 把css代码转化为js代码,css-loader是处理css文件的loader 'css-loader' ] }, { test: /\.less$/, use: getStyleLoaders("less-loader"), // 从右向左解析原则 // use: ["style-loader", "css-loader", "less-loader"] }, { test: /\.s[ac]ss$/, use: getStyleLoaders("sass-loader") }, { test: /\.js$/, exclude: /node_modules/, use: [ { loader: 'babel-loader', options: { presets: ['@babel/preset-env'], // cacheDirectory: true, // 开启babel缓存 // cacheCompression: false,// 关闭缓存文件压缩 // plugins: ['@babel/plugin-transform-runtime'], }, },] }, { test: /\.(gif|png|jpe?g)$/i, type: "asset", parser: { dataUrlCondition: { // 小于10kb的图片转成base64,减少请求数量 // 缺点:体积会大一点 maxSize: 10 * 1024, // 小于10kb }, }, generator: { // 输出图片的名称 filename: "imgs/[name].[contenthash:8][ext]", }, }, { test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/, //媒体文件 // 对文件原封不动的输出 type: "asset/resource", // generator: { // filename: "media/[name].[contenthash:8][ext]", // }, }, { test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/i, // 字体 type: "asset/resource", // generator: { // filename: "fonts/[name].[contenthash:8][ext]" // } }, ] }, ``` #### 3、配置eslint(可组装js、jsx检查工具) 我们打包前,要先保证代码正确,这个时候就用到了eslint 配置文件由很多种写法: .eslintrc.*:新建文件,位于项目根目录 .eslintrc .eslintrc.js .eslintrc.json 区别在于配置格式不一样 package.json 中eslintconfig:不需要创建文件,在原有文件基础上写ESLint 会查找和自动读取它们,所以以上配置文件只需要存在一个即可 - 在webpack4中是loder在webpack5中改为plugin ```bash npm install eslint-webpack-plugin eslint --save-dev ``` 我的代码里面配置@vue/cli-plugin-eslint 所以不用安装上面这个步骤 -- 参考链接webpack官网 plugin配置 [webpack官网](https://www.webpackjs.com/plugins/eslint-webpack-plugin) - 配置eslint-webpack-plugin 1. 下载 ```bash npm install eslint-webpack-plugin --D ``` 2. 引入 ```bash const ESLintPlugin = require('eslint-webpack-plugin'); ``` 3、在plugins中配置 ```javascript plugins:[ ... new ESLintPlugin({ // 配置哪些目录需要检查 context: path.resolve(__dirname, './src'), }), ] ``` - 在.eslintrc.*s中配置eslint规则 ```javascript // 继承eslint规则 extends:["eslint:recommended"] env :{ "node":true,//启用node中全局变量 "browser":true,//启用浏览器中全局变量 } parserOptions:{ "ecmaVersion":6, //使用es6语法 "sourceType": "module" //使用模块化语法 } rules:{ "no-var":2,//不能使用 var 定义变量 } ``` - 在根目录配置文件.eslintignore中配置忽略检查的文件 ``` dist ``` #### 4、配置babel(将高级的js语法转换成低版本的js语法) 配置好eslint之后,就是要配置babel,他能将高级的js语法转换成低版本的js语法,处理各种兼容问题。 1. 配置文件 配置文件由很多种写法: - babel.config.*:新建文件,位于项目根目录 - babel.config.js - babel.config.json .babelrc.*:新建文件,位于项目根目录 - .babelrc - .babelrc.is - .babelrc.json package.json 中babel:不需要创建文件,在原有文件基础上写 Babel会查找和自动读取它们,所以以上配置文件只需要存在一个即可 2. presets 预设 简单理解:就是一组 Babel插件,扩展 babel 功能 - @babel/preset-env : 一个智能预设允计您使用最新的JavaScript。 - @babel/preset-react: 一个用来编译 React jsx 语法的预设 - @babe1/preset-typescript :一个用来编译TypeScript 语法的预设 3. 在 Webpack 中使用 1.下载包 ```bash npm i babel-loader @babel/core @babel/preset-env -D ``` 我安装babel已包含上述插件,无需再安装 [babel官网配置](https://www.webpackjs.com/loaders/babel-loader/#install) 2. 在webpack中配置babel ```javascript module:{ { test: /\.js$/, exclude: /node_modules/, use: { loader: 'babel-loader', options: { presets: ['@babel/preset-env'], }, }, }, } ``` 3. 在babel.config.js中配置babel ```javascript module.exports = { // 智能预设能编译最新的es6 presets: ['@babel/preset-env'], }; ``` > 对于js来说何时用babel-loader何时用esbuild-loader > > - 主要功能:通过 Babel 转译 JavaScript 代码,支持 ES6+ 语法转换为兼容性更高的代码。 灵活性:支持多种插件和预设(如 @babel/preset-env、@babel/plugin-transform-runtime > 等),可以满足复杂的转译需求。 > - 生态丰富:Babel 的插件生态系统非常强大,能够处理各种语言特性(如 TypeScript、Flow 等)。 > - 速度较慢:由于 Babel 是基于 JavaScript 实现的,转译速度相对较慢,尤其是在大规模项目中。 使用场景 > - 当需要对现代 JavaScript 语法进行深度转译时(如支持 IE 浏览器)。 > - 当需要使用 Babel 插件来实现特定功能时(如 polyfill、代码优化等)。 esbuild-loader 特点 > - 主要功能:通过 esbuild 工具快速转译 JavaScript 代码,专注于性能优化。 > - 速度快:esbuild 是用 Go 语言编写的,转译速度远快于 Babel。 > - 简单易用:默认支持 ES6+ 语法转译,无需额外配置插件或预设。 > - 功能有限:相比 Babel,esbuild 的功能较为单一,不支持复杂的插件系统。 使用场景 > - 当项目对转译速度有较高要求时(如开发环境中的热更新)。 > - 当只需要简单的 ES6+ 语法转译,而不需要复杂的功能(如 polyfill 或特定插件) 我当前项目是vue2+webpack 所以用的是esbuild-loader #### 5、使用 html-webpack-plugin > html-webpack-plugin 是一个用于在 webpack 的构建过程中生成 HTML > 文件的插件。它允许您使用一个简单的模板文件,并自动将生成的 bundle 文件插入到模板文件中,从而生成一个完整的 HTML 文件。 > 使用方式如下: ```javascript new HtmlWebpackPlugin({ // 模版:以public/index.html为模板生成打包后的index.html template: path.resolve(__dirname, "./public/index.html"), BASE_URL: process.env.BASE_URL || '/' }), ``` #### 配置服务热更新 - 下载依赖 ```bash npm install wwebpack-dev-server --D ``` 在webpack.config.js中配置devServer ```javascript devServer: { static: { directory: path.resolve(__dirname, "./dist"), // 打包后的文件路径 directory:目录 }, open: true, //自动打开浏览器 compress: true, //启动gzip压缩 port: 9000, // 端口号 }, ``` - 启动命令: npx webpack serve #### 6、 css优化 MiniCssExtractPlugin > 本插件会将 CSS 提取到单独的文件中,为每个包含 CSS 的 JS 文件创建一个 CSS 文件,并且支持 CSS 和 SourceMaps > 的按需加载。 ```javascript const MiniCssExtractPlugin = require("mini-css-extract-plugin"); ``` 将style-loder 替换为 MiniCssExtractPlugin.loader ```javascript { test: /\.css$/, // MiniCssExtractPlugin.loader 最终会将css提取到单独的文件 use: [MiniCssExtractPlugin.loader, "css-loader"], // 从右向左解析原则 // use: ["style-loader", "css-loader"] } ``` 然后在插件中调用一下 ```javascript new MiniCssExtractPlugin({ filename: "css/[name].[contenthash:8].css" }), ``` #### 7、css兼容性处理 - 安装 ```bash npm i postcss-loader postcss postcss-preset-env -D ``` - 在loader中配置 ```javascript { test: /\.s[ac]ss$/, use: [ MiniCssExtractPlugin.loader, "css-loader", { loader: "postcss-loader", options: { plugins:['postcss-preset-env'],//能解决大多数兼容性问题 postcssOptions: { plugins: [["autoprefixer"]], }, }, }, "sass-loader", ], // scss的loader }, ``` - 在package.json中配置browserslist ``` "browserslist": [ "> 1%", // 全球超过1%的浏览器 "last 2 versions", // 最近两个版本 "not dead" // 排除已经不再维护的浏览器 ] ``` #### 7、CssMinimizerWebpackPlugin > CssMinimizerWebpackPlugin 是一个用于优化和压缩 CSS 的 webpack 插件。它使用 cssnano > 来优化和压缩 CSS,并支持 source maps 和 assets 中使用查询字符串。 - 安装依赖 ```bash npm install css-minimizer-webpack-plugin --save-dev ``` webpack官方给出的代码 ```javascript const MiniCssExtractPlugin = require('mini-css-extract-plugin'); const CssMinimizerPlugin = require('css-minimizer-webpack-plugin'); module.exports = { module: { rules: [ { test: /.s?css$/, use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader'], }, ], }, optimization: { minimizer: [ // 在 webpack@5 中,你可以使用 `...` 语法来扩展现有的 minimizer(即 `terser-webpack-plugin`),将下一行取消注释 // `...`, new CssMinimizerPlugin(), ], }, plugins: [new MiniCssExtractPlugin()], }; ``` 我直接在plugins中配置了CssMinimizerPlugin #### 8、启动常见问题处理 ```javascript ERROR in Template execution failed: ReferenceError: BASE URL is not defined ERROR in ReferenceError: BASE URL is not defined ``` ```javascript plugins: [ ... new DefinePlugin({ // window.ENV = 'production' ENV: JSON.stringify('production'), BASE_URL: '"../"' // 定义全局变量BASE_URL }), ], ``` ### webpack 高级配置 见下篇 [项目地址] (https://gitee.com/pear66/vue-webpack5) ### webpack 高级配置 #### 总结 我们从 4 个角度对 webpack 和代码进行了优化: - 1.提升开发体验 。使用 sourceMap让开发或上线时代码报错能有更加准确的错误提示。 - 2.提升 webpack 提升打包构建速度 。使用 HotmduleReplacement让开发时只重新编译打包更新变化了的代码,不变的代码使用缓存,从而使更新速度更快。 。使用 0ne0f让资源文件一旦被某个 loader 处理了,就不会继续遍历了,打包速度更快。 。使用 Include/Exclude排除或只检测某些文件,处理的文件更少,速度更快。 。使用cache 对 eslint 和 babel 处理的结果进行缓存,让第二次打包速度更快。 。使用 Thead 多进程处理 esint和 babel 任务,速度更快。(需要注意的是,进程启动通信都有开销的,要在比较多代码处理时使用才有效 果) - 3.减少代码体积 。使用 Tree shaking剔除了没有使用的多余代码,让代码体积更小。 。使用 @babel/plugin-transform-runtime 插件对 babel 进行处理,让辅助代码从中引入,而不是每个文件都生成辅助代码,从而体积更小。。使用 image miniizer 对项目中图片进行压缩,体积更小,请求速度更快。(需要注意的是,如果项目中图片都是在线链接,那么就不需要了。本地项目静态图片才需要进行压缩。) - 4.优化代码运行性能 。使用 code split 对代码进行分割成多个i5文件,从而便单个文件体积更小,并行加载is速度更快。并通过 import 动态导入语法进行按需加载,从而达到需要使用时才加载该资源,不用时不加载资源。 使用 Preload/Prefetch,对代码进行提前加载,等未来需要使用时就能直接使用,从而用户体验更好。使用 Network cache能对输出资源文件进行更好的命名,将来好做缓存,从而用户体验更好。 。便用 core-js 对js 进行兼容性处理,让我们代码能运行在低版本浏览器。 。使用PA能让代码离线也能访问,从而提升用户体验。 #### devtool 配置 (找到报错位置) 此选项控制是否生成,以及如何生成 source map。使用 SourceMapDevToolPlugin 进行更细粒度的配置。查看 source-map-loader 来处理已有的 source map。 SourceMap(源代码映射)是一个用来生成源代码与构建后代码--映射的文件的方案。它会生成一个 xx.map 文件,里面包含源代码和构建后代码每一行、每一列的映射关系。当构建后代码出错了,会通过 xxx.map 文件,从构建后代码出错位置找到映射后源代码出错位置,从而让浏览器提示源代码文件出错位置,帮助我们更快的找到错误根源。 开发模式用 ``` devtool: 'cheap-module-source-map', ``` - 优点:打包编译速度快,只包含行映射 - 缺点:没有列映射 生产模式用 ``` devtool: 'source-map', ``` - 优点:包含行/列映射 - 缺点:打包编译速度更慢 build: slowest rebuild: slowest #### 优化打包速度 HMR (HotModuleReplacement),即热模块替换,是 webpack 的一个功能,它可以在运行时更新模块,而无需完全刷新整个页面。 ``` devServer: { ... hot:true, // 提供HMR功能,只更新某个模块,没有替换整个项目 }, ``` 在模块中判断 ``` if(module.hot){ module.hot.accept('./xxx') } ``` 实际开发并不需要上述这样,直接配置loader,以vule为例 vue-loader,生产模式不需要 #### OneOf 每个文件只被一个loader处理 ``` module: { rules: [ // oneOf 不支持 vue-loader ,要单独拿出来 { test: /\.vue$/, loader: "vue-loader", }, // 每个文件只有一个loader配置处理 { oneOf: [ { test: /\.(gif|png|jpe?g)$/i, type: "asset", parser: { dataUrlCondition: { // 小于10kb的图片转成base64,减少请求数量 // 缺点:体积会大一点 maxSize: 10 * 1024, // 小于10kb }, }, generator: { // 输出图片的名称 filename: "imgs/[name].[contenthash:8][ext]", }, }, ] } ], }, ``` - 报错 [VueLoaderPlugin Error] vue-loader 15 currently does not support vue rules with oneof 解决方案:将vue-loader 移到配置外面,单独拿出来 #### include/exclude 处理某些文件或者排除某些文件 ``` module: { rules: [ { test: /\.(js|ts|jsx|tsx)$/, include: path.resolve(__dirname, 'src'), // exclude: /node_modules/, // loader:"babel-loader", loader: 'esbuild-loader', generator: { target: 'es2015' } }, ] } ``` include和exclude的只写一个即可 ``` plugins: [ new ESLintPlugin({ // 配置哪些目录需要检查 context: path.resolve(__dirname, './src'), exclude: 'node_modules',// 不写 默认也有 }), ] ``` #### cache 缓存 (提升后面几次的打包速度) 对eslint检查和babel编译进行缓存,提升打包速度 ``` { test: /\.js$/, exclude: /node_modules/, use: { loader: 'babel-loader', options: { presets: ['@babel/preset-env'], cacheDirectory: true, // 开启babel缓存 cacheCompression: false,// 关闭缓存文件压缩 }, }, }, ``` eslint 开启缓存 ``` new ESLintPlugin({ // 配置哪些目录需要检查 context: path.resolve(__dirname, './src'), exclude: 'node_modules',// 不写 默认也有 cache: true,// 开启缓存 cacheLocation: path.resolve(__dirname, '../node_modules/.cache/eslintcache'), }), ``` #### 多进程打包 ``` const os = require('os'); const threads = os.cpus().length; ``` - 下载 thread-loader ``` npm install thread-loader --D ``` 在loader配置多进程 ``` { test: /\.js$/, exclude: /node_modules/, use: [{ loader: 'thread-loader', options: { workers: threads, // 开启几个子进程去完成 } }, { loader: 'babel-loader', options: { presets: ['@babel/preset-env'], cacheDirectory: true, // 开启babel缓存 cacheCompression: false,// 关闭缓存文件压缩 }, },] }, ``` 在eslint中开启多进程 ``` new ESLintPlugin({ // 配置哪些目录需要检查 context: path.resolve(__dirname, './src'), cache: true,// 开启缓存 cacheLocation: path.resolve(__dirname, '../node_modules/.cache/eslintcache'), threads, }), ``` 引入压缩的插件 ``` const TerserWebpackPlugin = require("terser-webpack-plugin"); ``` 在plugins中配置 ``` new TerserWebpackPlugin({ parallel: threads, // 开启多进程 extractComments: false, // 移除注释 terserOptions: { compress: { pure_funcs: ['console.log'], // 移除console.log }, }, }), ``` 在optimization添加压缩配置 ``` // 用于处理压缩 optimization: { ... minimizer: [ // CssMinimizerPlugin、TerserWebpackPlugin 也可以放在plugins中 new CssMinimizerPlugin(), new TerserWebpackPlugin({ parallel: threads, // 开启多进程 extractComments: false, // 移除注释 terserOptions: { compress: { pure_funcs: ['console.log'], // 移除console.log }, }, }), ], }, ``` #### 减少代码体积 Tree Shaking 减少babel体积 - 下载 禁用babel自动对每个文件的runtime注入,而是引入@babel/plugin-transform-runtime 是辅助代码从这里引入 ``` npm i @babel/plugin-transform-runtime --D ``` 在babel中配置 ``` { test: /\.js$/, exclude: /node_modules/, 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'], }, },] }, ``` #### 压缩图片 下载包 ``` npm i image-minimizer-webpack-plugin --D ``` 无损压缩(包下载不下来) ``` npm install imagemin-gifsicle imagemin-jpegtran imagemin-optipng imagemin-svgo --D ``` 有损压缩 ``` npm install imagemin-gifsicle imagemin-jpegtran imagemin-pngquant imagemin-svgo --D ``` 包不好下 ``` 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" } } ] }, ], ] } } }) ], }, ``` #### 多入口 ``` const HtmlWebpackPlugin=require("html-webpack-plugin"); module.exports ={ // entry:'./src/main.js',// 只有一个入口文件,单入口 entry:{ // 有多个入口文件,多入口 app:"./src/app.js" main:"./src/main.js" } output:{ path: path.resolve( dirname,"dist"), filename: "[name].js",// webpack命名方式,[name]以文件名自己命名filename } plugins:[ new HtmlWebpackPlugin({template:path.resolve( dirname,"public/index.html")}) ], mode:"production" } ``` #### 多入口想提取公共模块,这个时候就用到了代码分割 ``` optimization: { minimize: true, // 强制启用压缩 // 对代码进行分割 splitChunks: { chunks: 'all', // 以下是默认值 // minsize:20000,//分割代码最小的大小 // minRemainingsize:0,//类似于minsize,最后确保提取的文件大小不能为0// minChunks:1,//至少被引用的次数,满足条件才会代码分割 // maxAsyncRequests:3e,/按需加载时并行加载的文件的最大数量 // maxInitialRequests:30,//入口js文件最大并行请求数量 // enforcesizeThreshold:50000, // 超过50kb一定会单独打包(此时会忽略minRemainingsize、maxAsyncRequests、maxInitialRegquests) //cacheGroups:{// 组,哪些模块要打包到一个组) // defaultVendors:{//组名 // test:/[\V/]node_modules[\\/]/,//需要打包到一起的模块 // priority:-10,//权重(越大越高) // reuseExistingchunk:true,//如果当前 chunk 包含已从主 bundle 中拆分出的模块,则它将被重用, // 而不是生成新的模块 // }, // default:{ // 其他没有写的配置会使用上面的默认值 // { // minChunks:2,//这里的minChunks权重更大 // priority: -20, // reuseExistingchunk: true, // } }, // runtimeChunk: 'single', minimizer: [ new CssMinimizerPlugin(), ] }, ``` #### chunk统一命名 ``` output: { clean: true, // 清理 /dist 文件夹 // filename: "js/main.js", // 打包后的文件名称 filename: "js/[name].[contenthash:8].js", // 打包后的文件名称 // 打包输出的其他文件名称 chunkFilename: "js/[name].[contenthash:8].chunk.js", path: path.resolve(__dirname, "../dist"), // 打包后的目录 // 图片 等字体通过type: asset处理资源命名方式 assetModuleFilename: 'media/[name].[contenthash:8][ext][query]', }, ``` ``` new MiniCssExtractPlugin({ filename: "css/[name].[contenthash:8].css" }), ``` 添加 移除loader中字体、媒体文件的命名规则 ``` // generator: { // filename: "fonts/[name].[contenthash:8][ext][query]" // } ``` #### Preload和Prefetch - Preload :告诉浏览器立即加载资源。 - Prefetch :告诉浏览器在空闲时才开始加载资源。 它们共同点: 。都只会加载资源,并不执行。 。都有缓存。 它们区别: Preload 加载优先级高,Prefetch 加载优先级低 只能加载当前页面需要使用的资源, Prefetch 可以加载当前页面资源,也可以加载下一个页面需要使用的资源。reloa 总结: 。当前页面优先级高的资源用 Preload 加载。 。下一个页面需要使用的资源用Prefetch 加载 它们的问题:兼容性较差, 。我们可以去 CanlUseB 网站查询 API 的兼容性问题Preload 相对于 Prefetch 兼容性好一点。 [查看兼容](https://caniuse.com/?search=preload) #### 配置缓存,文件发生变化时,只有main 和runtime.js会重新打包,其他文件不变 ``` runtimeChunk:{ name:(entrypoint)=>runtime~${entrypoint.name}.js` } ``` #### Core-js 过去我们使用 babel 对js 代码进行了兼容性处理,其中使用@babe/preset-env 智能预设来处理兼容性问题它能将 ES6 的一些语法进行编译转换,比如箭头函数、点点点运算符等。但是如果是 async 函数、promise 对象、数组的一些方法(includes)等,它没办法处理 所以此时我们js 代码仍然存在兼容性问题,一旦遇到低版本浏览器会直接报错。所以我们想要将js 兼容性问题彻底解决 core-js 是专门用来做ES6 以及以上API的 polyfill。 polyfi11 翻译过来叫做垫片/补丁。就是用社区上提供的一段代码,让我们在不兼容某些新特性的浏览器上,使用该新特性。 例如:Promise 就没有被打包 ``` return new Promise(resolve => { resolve("成功"); }); ``` 解决方案: - 通过在代码中按需引入core-js的Promise - 在babel.config.js中配置core-js ``` module.exports = { presets: [ '@babel/preset-env', { useBuiltIns: "usage", //按需加载自动引入 corejs: 3, } ] }; ``` #### PWA 开发 Web App 项目,项目一旦处于网络离线情况,就没法访问了。我们希望给项目提供离线体验。 渐进式网络应用程序(progressiveweb application·PWA):是一种可以提供类似于 native app(原生应用程序) 体验的 Web App 的技术。 其中最重要的是,在 离线(offline)时应用程序能够继续运行功能。内部通过 Service Workers 技术实现的。 - 下载 ``` npm install workbox-webpack-plugin --save-dev ``` npm run build 现在你可以看到,生成了两个额外的文件:service-worker.js 和名称冗长的 precache-manifest.b5ca1c555e832d6fbf9462efd29d27eb.js。service-worker.js 是 Service Worker 文件,precache-manifest.b5ca1c555e832d6fbf9462efd29d27eb.js 是 service-worker.js 引用的文件,所以它也可以运行。你本地生成的文件可能会有所不同,但是应该会有一个 service-worker.js 文件。 - 注册 Service Worker ``` 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); }); }); } ``` 启动会发现未成功,这个时候要安装server npm i server -g 启动 sever dist [具体可参考](https://www.webpackjs.com/guides/progressive-web-application/#adding-workbox)