当前位置: 首页 > news >正文

个人网站数据库大小网站名字和域名

个人网站数据库大小,网站名字和域名,用什么网站做框架图,网站建设私单合同webpack 1. 简介1.1 webpack 是什么1.2 webpack 五个核心概念1.2.1 入口 - Entry1.2.2 出口 - Output1.2.3 Loader1.2.4 插件 - Plugins1.2.6 模式 - Mode 2. webpack 初体验2.1 初始化配置2.1.1. 准备2.1.2. 写代码2.1.3 编译打包应用 3. webpack 开发环境的基本配置3.1 打包样… webpack 1. 简介1.1 webpack 是什么1.2 webpack 五个核心概念1.2.1 入口 - Entry1.2.2 出口 - Output1.2.3 Loader1.2.4 插件 - Plugins1.2.6 模式 - Mode 2. webpack 初体验2.1 初始化配置2.1.1. 准备2.1.2. 写代码2.1.3 编译打包应用 3. webpack 开发环境的基本配置3.1 打包样式资源3.2 打包 HTML 资源3.3 打包图片资源3.4 打包其他资源3.5 开发环境配置 - devServer总结 4. webpack 生产环境的基本配置4.1 提取 css 成单独文件4.2 css 兼容性处理4.3 压缩 css4.4 js语法检查4.5 js 兼容性处理4.6 js 压缩4.7 HTML 压缩4.8 生产环境配置 5. webpack 优化配置5.1 开发环境性能优化5.1.1 优化打包构建速度HMR 5.1.2 优化代码调试source-map 5.2 生产环境性能优化5.2.1 优化打包构建速度oneOfbabel缓存多进程打包externalsdll 5.2.2 优化代码运行的性能缓存(hash-chunkhash-contenthash)tree shakingcode split懒加载/预加载PWA渐进式 Web 应用配置详解 1. 简介 1.1 webpack 是什么 webpack 是一种前端资源构建工具一个静态模块打包器(module bundler)。 在 webpack 看来, 前端的所有资源文件(js/json/css/img/less/…)都会作为模块处理。 它将根据模块的依赖关系进行静态分析打包生成对应的静态资源(bundle)。 1.2 webpack 五个核心概念 entry入口指示打包的起点文件output输出指示打包资源bundles输出路径和命名loader处理非js文件webpack自身只理解js、json相当于翻译官plugins功能插件可以做到优化、压缩、定义环境变量等mode模式分为 development和production 模式 1.2.1 入口 - Entry 入口(Entry)是 webpack 分析构建内部依赖图的起点模块(模块就是一个文件)。 // webpack.config.js: module.exports {entry: ./path/to/my/entry/file.js };1.2.2 出口 - Output output 属性告诉 webpack 在哪里输出它所创建的 bundles以及如何命名这些文件默认值为 ./dist。 /*webpack.config.js webpack的配置文件作用: 指示 webpack 干哪些活当你运行 webpack 指令时会加载里面的配置所有构建工具都是基于nodejs平台运行的~模块化默认采用commonjs。 */ const path require(path); module.exports {entry: ./path/to/my/entry/file.js,output: {// 输出路径// --dirname: nodeJs的变量代表当前文件的绝对路径// resolve: nodeJs里path模块的方法用来拼接绝对路径path: path.resolve(__dirname, dist),// 输出文件名filename: my-first-webpack.bundle.js} };1.2.3 Loader loader 让 webpack 能够去处理那些非 JavaScript 文件webpack 自身只理解JavaScript loader 可以将所有类型的文件转换为 webpack 能够处理的有效模块。 loader的使用 需要先下载无需requrie。 // webpack.config.js: const { resolve } require(path); const config {output: {filename: my-first-webpack.bundle.js,path: resolve(__dirname, dist)},module: {rules: [// 不同类型的文件必须配置不同的规则来处理{test: /\.css$/, // 匹配什么样的文件// use数组中loader的执行顺序从下到上从右到左后进先出use: [style-loader, css-loader ]}]} }; module.exports config;1.2.4 插件 - Plugins 插件(Plugins)可以用于执行范围更广(比loader)的任务。插件的范围包括从打包优化和压缩一直到重新定义环境中的变量等。 plugin的使用 需要先下载还需requrie。 // webpack.config.js: const HtmlWebpackPlugin require(html-webpack-plugin); // 通过 npm 安装 const webpack require(webpack); // 用于访问内置插件 const config {module: {rules: [{ test: /\.txt$/, use: raw-loader }]},plugins: [new HtmlWebpackPlugin({template: ./src/index.html})] }; module.exports config;1.2.6 模式 - Mode 模式(Mode)指示 webpack 使用相应模式的配置 mode分为 ‘development’ 和 ‘production’;生产环境和开发环境将 ES6 模块化编译成浏览其能识别的模块化生产环境比开发环境多一个压缩js代码 选项描述特点development会将DefinePlugin中process.env.NODE_ENV的值设置为development。启用NamedChunksPlugin和NamedModulesPlugin。能让代码本地调试运行的环境production会将DefinePlugin中process.env.NODE_ENV的值设置为production。启用FlagDependencyUsagePlugin, FlagIncludedChunksPlugin, ModuleConcatenationPlugin, NoEmitOnErrorsPlugin, OccurrenceOrderPlugin, SideEffectsFlagPlugin 和 TerserPlugin。能让代码优化上线运行的环境 // webpack.config.js: module.exports {mode: production };2. webpack 初体验 2.1 初始化配置 2.1.1. 准备 初始化 package.json下载并安装 webpack //初始化 package.json npm init //下载并安装 webpack npm i webpack webpack-cli -D // 也下载loader和 plugins npm i xxx-loader xxx-plugin -D2.1.2. 写代码 需要在项目的根目录写一个名为webpack.config.js的配置文件。 webpack初体验 ├── src │ └── index.js │ └── test.json ├── webpack.config.js ├── package.json代码 // 1. src/index.js import data from ./test.json; console.log(data); function add(x, y) {return x y; } add(1, 2) console.log(add(1, 2))// 2. src/test.json {testJson: test json }// 3. webpack.config.js const { resolve } require(path); // module.exports {entry: ./src/index.js,output: {filename: built.js,path: resolve(__dirname, build)},module: {rules: [{test: /\.css$/,use: [style-loader,css-loader ]}]},plugins: [],mode: development } 2.1.3 编译打包应用 在package.json 中添加 脚本命令dev: SET NODE_OPTIONS--openssl-legacy-provider webpack //package.json {name: webpack_test,version: 1.0.0,description: ,main: index.js,scripts: {test: echo \Error: no test specified\ exit 1,dev: SET NODE_OPTIONS--openssl-legacy-provider webpack},author: ,license: ISC,devDependencies: {css-loader: ^5.0.0,style-loader: ^2.0.0,webpack: ^4.41.6,webpack-cli: ^3.3.11} }# 打包执行 npm run dev3. webpack 开发环境的基本配置 3.1 打包样式资源 创建文件 下载安装 loader 包 npm i css-loader style-loader less-loader less -D修改配置文件 /*webpack.config.js webpack的配置文件作用: 指示 webpack 干哪些活当你运行 webpack 指令时会加载里面的配置所有构建工具都是基于nodejs平台运行的~模块化默认采用commonjs。 */// resolve用来拼接绝对路径的方法 const { resolve } require(path);module.exports {// webpack配置// 入口起点entry: ./src/index.js,// 输出output: {// 输出文件名filename: built.js,// 输出路径// __dirname nodejs的变量代表当前文件的目录绝对路径path: resolve(__dirname, build)},// loader的配置module: {rules: [// 详细loader配置// 不同文件必须配置不同loader处理{// 匹配哪些文件test: /\.css$/,// 使用哪些loader进行处理use: [// use数组中loader执行顺序从右到左从下到上 依次执行// 创建style标签将js中的样式资源插入进行添加到head中生效style-loader,// 将css文件变成commonjs模块加载js中里面内容是样式字符串(转换后得到的commonjs模块可以理解为用js给元素动态添加样式的那种代码css-loader]},{test: /\.less$/,use: [style-loader,css-loader,// 将less文件编译成css文件// 需要下载 less-loader和lessless-loader]}]},// plugins的配置plugins: [// 详细plugins的配置],// 模式mode: development, // 开发模式// mode: production } 运行指令: webpack 3.2 打包 HTML 资源 创建文件 下载安装 plugin 包 npm install --save-dev html-webpack-plugin修改配置文件 /*loader: 1. 下载 2. 使用配置loaderplugins: 1. 下载 2. 引入 3. 使用 */ const { resolve } require(path); const HtmlWebpackPlugin require(html-webpack-plugin);module.exports {entry: ./src/index.js,output: {filename: built.js,path: resolve(__dirname, build)},module: {rules: [// loader的配置]},plugins: [// plugins的配置// html-webpack-plugin// 功能默认会创建一个空的HTML自动引入打包输出的所有资源JS/CSS// 需求需要有结构的HTML文件/*** html-webpack-plugin* 1) 不传参的情况 - new HTMLWebpackPlugin()会在配置的output文件夹创建一个空的html, 自动引入打包输出的所有资源包括js, css...* 2) 参数template复制设置的./src/index.html文件到配置的output文件夹并自动引入打包输出的所有资源*/new HtmlWebpackPlugin({// 复制 ./src/index.html 文件并自动引入打包输出的所有资源JS/CSStemplate: ./src/index.html})],mode: development }; 运行指令: webpack 3.3 打包图片资源 创建文件 下载安装 loader 包 npm install --save-dev html-loader url-loader file-loader修改配置文件 const { resolve } require(path); const HtmlWebpackPlugin require(html-webpack-plugin);module.exports {entry: ./src/index.js,output: {filename: built.js,path: resolve(__dirname, build)},module: {rules: [{test: /\.less$/,// 要使用多个loader处理用useuse: [style-loader, css-loader, less-loader]},{// 问题默认处理不了html中img图片// 处理图片资源test: /\.(jpg|png|gif)$/,// 使用一个loader// 下载 url-loader file-loaderloader: url-loader,options: {// 图片大小小于8kb就会被base64处理// 优点: 减少请求数量减轻服务器压力// 缺点图片体积会更大文件请求速度更慢limit: 8 * 1024,// 问题因为url-loader默认使用es6模块化解析而html-loader引入图片是commonjs// 解析时会出问题[object Module]// 解决关闭url-loader的es6模块化使用commonjs解析esModule: false,// 给图片进行重命名// [hash:10]取图片的hash的前10位// [ext]取文件原来扩展名name: [hash:10].[ext]}},{test: /\.html$/,// 处理html文件的img图片负责引入img从而能被url-loader进行处理loader: html-loader}]},plugins: [new HtmlWebpackPlugin({template: ./src/index.html})],mode: development }; 运行指令: webpack 3.4 打包其他资源 创建文件 下载安装 loader 包 npm install --save-dev html-loader url-loader file-loader修改配置文件 const { resolve } require(path); const HtmlWebpackPlugin require(html-webpack-plugin);module.exports {entry: ./src/index.js,output: {filename: built.js,path: resolve(__dirname, build)},module: {rules: [{test: /\.css$/,use: [style-loader, css-loader]},// 打包其他资源(除了html/js/css资源以外的资源,比如字体文件等){// 排除css/js/html资源exclude: /\.(css|js|html|less)$/,loader: file-loader,options: {name: [hash:10].[ext]}}]},plugins: [new HtmlWebpackPlugin({template: ./src/index.html})],mode: development }; 运行指令: webpack 3.5 开发环境配置 - devServer devServer开发服务器用来自动化自动编译自动打开浏览器自动刷新浏览器特点只会在内存中编译打包不会有任何输出不会在项目中新建一个文件夹 创建文件 修改配置文件 /*开发环境配置能让代码运行运行项目指令webpack 会将打包结果输出出去npx webpack-dev-server 只会在内存中编译打包没有输出 */const { resolve } require(path); const HtmlWebpackPlugin require(html-webpack-plugin);module.exports {entry: ./src/js/index.js,output: {filename: js/built.js,path: resolve(__dirname, build)},module: {rules: [// loader的配置{// 处理less资源test: /\.less$/,use: [style-loader, css-loader, less-loader]},{// 处理css资源test: /\.css$/,use: [style-loader, css-loader]},{// 处理图片资源test: /\.(jpg|png|gif)$/,loader: url-loader,options: {limit: 8 * 1024,name: [hash:10].[ext],// 关闭es6模块化esModule: false,outputPath: imgs}},{// 处理html中img资源test: /\.html$/,loader: html-loader},{// 处理其他资源exclude: /\.(html|js|css|less|jpg|png|gif)/,loader: file-loader,options: {name: [hash:10].[ext],outputPath: media}}]},plugins: [// plugins的配置new HtmlWebpackPlugin({template: ./src/index.html})],mode: development,devServer: {// 项目构建后路径contentBase: resolve(__dirname, build),// 启动gzip压缩compress: true,// 端口号port: 3000,// 自动打开浏览器open: true} }; 运行指令: npx webpack-dev-server总结 打包样式资源 安装 css-loader, style-loader, less-loader, less。配置 webpack.config.js 来处理 .css 和 .less 文件。 打包 HTML 资源 安装 html-webpack-plugin。使用 HtmlWebpackPlugin 自动生成包含 JS/CSS 的 HTML 文件。 打包图片资源 安装 url-loader, file-loader, html-loader。配置 url-loader 处理图片资源支持 base64 编码。 打包其他资源 使用 file-loader 处理非 CSS/JS/HTML 资源。 开发环境配置 配置 devServer 自动编译、自动打开浏览器并实时刷新。设置 contentBase, compress, port, open 等选项。 4. webpack 生产环境的基本配置 4.1 提取 css 成单独文件 下载安装包 下载插件 npm install --save-dev mini-css-extract-plugin修改配置文件 const { resolve } require(path); const HtmlWebpackPlugin require(html-webpack-plugin); const MiniCssExtractPlugin require(mini-css-extract-plugin);module.exports {entry: ./src/js/index.js,output: {filename: js/built.js,path: resolve(__dirname, build)},module: {rules: [{test: /\.css$/,use: [// 创建style标签将样式放入// style-loader, // 这个loader取代style-loader。作用提取js中的css成单独文件MiniCssExtractPlugin.loader,// 将css文件整合到js文件中css-loader]}]},plugins: [new HtmlWebpackPlugin({template: ./src/index.html}),new MiniCssExtractPlugin({// 对输出的css文件进行重命名filename: css/built.css})],mode: development }; 运行指令: webpack 4.2 css 兼容性处理 创建文件 下载 loader npm install --save-dev postcss-loader postcss-preset-env修改配置文件 const { resolve } require(path); const HtmlWebpackPlugin require(html-webpack-plugin); const MiniCssExtractPlugin require(mini-css-extract-plugin);// 设置nodejs环境变量 // process.env.NODE_ENV development;module.exports {entry: ./src/js/index.js,output: {filename: js/built.js,path: resolve(__dirname, build)},module: {rules: [{test: /\.css$/,use: [MiniCssExtractPlugin.loader,css-loader,/*css兼容性处理postcss -- postcss-loader postcss-preset-env帮postcss找到package.json中browserslist里面的配置通过配置加载指定的css兼容性样式browserslist: {// 开发环境 -- 设置node环境变量process.env.NODE_ENV developmentdevelopment: [last 1 chrome version,last 1 firefox version,last 1 safari version],// 生产环境默认是看生产环境production: [0.2%,not dead,not op_mini all]}*/// 使用loader的默认配置// postcss-loader,// 修改loader的配置{loader: postcss-loader,options: {ident: postcss,plugins: () [// postcss的插件require(postcss-preset-env)()]}}]}]},plugins: [new HtmlWebpackPlugin({template: ./src/index.html}),new MiniCssExtractPlugin({filename: css/built.css})],mode: development }; 修改 package.json browserslist: {development: [last 1 chrome version,last 1 firefox version,last 1 safari version],production: [0.2%,not dead,not op_mini all] }运行指令: webpack 4.3 压缩 css 创建文件 下载安装包 npm install --save-dev optimize-css-assets-webpack-plugin修改配置文件 const { resolve } require(path); const HtmlWebpackPlugin require(html-webpack-plugin); const MiniCssExtractPlugin require(mini-css-extract-plugin); const OptimizeCssAssetsWebpackPlugin require(optimize-css-assets-webpack-plugin)// 设置nodejs环境变量 // process.env.NODE_ENV development;module.exports {entry: ./src/js/index.js,output: {filename: js/built.js,path: resolve(__dirname, build)},module: {rules: [{test: /\.css$/,use: [MiniCssExtractPlugin.loader,css-loader,{loader: postcss-loader,options: {ident: postcss,plugins: () [// postcss的插件require(postcss-preset-env)()]}}]}]},plugins: [new HtmlWebpackPlugin({template: ./src/index.html}),new MiniCssExtractPlugin({filename: css/built.css}),// 压缩cssnew OptimizeCssAssetsWebpackPlugin()],mode: development }; 运行指令: webpack 4.4 js语法检查 创建文件 下载安装包 npm install --save-dev eslint-loader eslint eslint-config-airbnb-base eslint-plugin-import修改配置文件 const { resolve } require(path); const HtmlWebpackPlugin require(html-webpack-plugin);module.exports {entry: ./src/js/index.js,output: {filename: js/built.js,path: resolve(__dirname, build)},module: {rules: [/*语法检查 eslint-loader eslint注意只检查自己写的源代码第三方的库是不用检查的设置检查规则package.json中eslintConfig中设置~eslintConfig: {extends: airbnb-base}airbnb -- eslint-config-airbnb-base eslint-plugin-import eslint*/{test: /\.js$/,exclude: /node_modules/,loader: eslint-loader,options: {// 自动修复eslint的错误fix: true}}]},plugins: [new HtmlWebpackPlugin({template: ./src/index.html})],mode: development }; 配置 package.json eslintConfig: { extends: airbnb-base, env: { browser: true } }运行指令: webpack 4.5 js 兼容性处理 JS兼容性处理 1什么是JS兼容性处理 其实就是把ES6及以上后边简写为ES6新增的语法、API处理成ES5及以下的版本解决某些浏览器ie上的兼容性报错问题。 2Babel简介 Babel 是一个工具链主要用于在当前和旧的浏览器或环境中将ES6代码转换为JavaScript向后兼容版本的代码。 3polyfill是啥 ⁉️不知道大家之前有没有过这种疑问只知道babel是处理ES6兼容的polyfill分别是干嘛的 ️其实ES6语法和新增的API需要分开进行处理polyfill是针对新增API的~比如箭头函数是新增语法Promise是新增的API 4请大家跟我一起看一段代码下面JS兼容性处理相关内容将以这个作为例子 console.log(add(2, 5));// 新API const promise new Promise(resolve { setTimeout(() {console.log(定时器执行完了~);resolve(); }, 1000); });console.log(promise); 上面代码如果不做任何兼容性处理运行结果如下 ie无法识别ES6的内容 下载安装包 npm install --save-dev babel-loader babel/core babel/preset-env babel/polyfill core-js修改配置文件 const { resolve } require(path); const HtmlWebpackPlugin require(html-webpack-plugin);module.exports {entry: ./src/js/index.js,output: {filename: js/built.js,path: resolve(__dirname, build)},module: {rules: [/*js兼容性处理babel-loader babel/core 1. 基本js兼容性处理 -- babel/preset-env问题只能转换基本语法如promise高级语法不能转换2. 全部js兼容性处理 -- babel/polyfill 问题我只要解决部分兼容性问题但是将所有兼容性代码全部引入体积太大了~3. 需要做兼容性处理的就做按需加载 -- core-js*/ {test: /\.js$/,exclude: /node_modules/,loader: babel-loader,options: {// 预设指示babel做怎么样的兼容性处理presets: [[babel/preset-env,{// 按需加载/** https://babeljs.io/docs/en/babel-preset-env#usebuiltins* useBuiltIns配置babel/preset-env如何处理polyfills取“usage”“entry”“false”之一默认为“false”* - 当使用usage或entry选项时babel/preset-env将添加对core-js模块的直接引用类似import或require。这意味着core-js将相对于文件本身进行解析并且按需引入。*/useBuiltIns: usage,// 指定core-js版本corejs: {version: 3},// 指定兼容性做到哪个版本浏览器targets: {chrome: 60,firefox: 60,ie: 9,safari: 10,edge: 17}}]]}}]},plugins: [new HtmlWebpackPlugin({template: ./src/index.html})],mode: development }; 运行指令: webpack 4.6 js 压缩 修改配置文件 const { resolve } require(path); const HtmlWebpackPlugin require(html-webpack-plugin);module.exports {entry: ./src/js/index.js,output: {filename: js/built.js,path: resolve(__dirname, build)},plugins: [new HtmlWebpackPlugin({template: ./src/index.html})],// 生产环境下会自动压缩js代码mode: production }; 运行指令: webpack 4.7 HTML 压缩 修改配置文件 const { resolve } require(path); const HtmlWebpackPlugin require(html-webpack-plugin);module.exports {entry: ./src/js/index.js,output: {filename: js/built.js,path: resolve(__dirname, build)},plugins: [new HtmlWebpackPlugin({template: ./src/index.html,// 压缩html代码minify: {// 移除空格collapseWhitespace: true,// 移除注释removeComments: true}})],mode: production }; 运行指令:webpack 4.8 生产环境配置 const { resolve } require(path); const MiniCssExtractPlugin require(mini-css-extract-plugin); const OptimizeCssAssetsWebpackPlugin require(optimize-css-assets-webpack-plugin); const HtmlWebpackPlugin require(html-webpack-plugin);// 定义nodejs环境变量决定使用browserslist的哪个环境 process.env.NODE_ENV production;// 复用loader const commonCssLoader [MiniCssExtractPlugin.loader,css-loader,{// 还需要在package.json中定义browserslistloader: postcss-loader,options: {ident: postcss,plugins: () [require(postcss-preset-env)()]}} ];module.exports {entry: ./src/js/index.js,output: {filename: js/built.js,path: resolve(__dirname, build)},module: {rules: [{test: /\.css$/,use: [...commonCssLoader]},{test: /\.less$/,use: [...commonCssLoader, less-loader]},/*正常来讲一个文件只能被一个loader处理。当一个文件要被多个loader处理那么一定要指定loader执行的先后顺序先执行eslint 在执行babel*/{// 在package.json中eslintConfig -- airbnbtest: /\.js$/,exclude: /node_modules/,// 优先执行enforce: pre,loader: eslint-loader,options: {fix: true}},{test: /\.js$/,exclude: /node_modules/,loader: babel-loader,options: {presets: [[babel/preset-env,{useBuiltIns: usage,corejs: {version: 3},targets: {chrome: 60,firefox: 50}}]]}},{test: /\.(jpg|png|gif)/,loader: url-loader,options: {limit: 8 * 1024,name: [hash:10].[ext],outputPath: imgs,esModule: false}},{test: /\.html$/,loader: html-loader},{exclude: /\.(js|css|less|html|jpg|png|gif)/,loader: file-loader,options: {outputPath: media}}]},plugins: [new MiniCssExtractPlugin({filename: css/built.css}),new OptimizeCssAssetsWebpackPlugin(),new HtmlWebpackPlugin({template: ./src/index.html,minify: {collapseWhitespace: true,removeComments: true}})],mode: production }; 5. webpack 优化配置 5.1 开发环境性能优化 5.1.1 优化打包构建速度 HMR Hot Module Replacement也称为HMR是一种在应用程序运行时替换、添加或删除模块的技术无需完全刷新页面就能更新这些模块。 修改 JS 文件无需刷新页面而能够直接在页面进行代码更新。修改 CSS 文件无需刷新页面改动的样式能直接呈现。 修改配置文件 /*HMR: hot module replacement 热模块替换 / 模块热替换作用一个模块发生变化只会重新打包这一个模块而不是打包所有模块 极大提升构建速度样式文件可以使用HMR功能因为style-loader内部实现了~js文件默认不能使用HMR功能 -- 需要修改js代码添加支持HMR功能的代码注意HMR功能对js的处理只能处理非入口js文件的其他文件。html文件: 默认不能使用HMR功能.同时会导致问题html文件不能热更新了~ 不用做HMR功能解决修改entry入口将html文件引入 */const { resolve } require(path); const HtmlWebpackPlugin require(html-webpack-plugin);module.exports {entry: [./src/js/index.js, ./src/index.html],output: {filename: js/built.js,path: resolve(__dirname, build)},module: {rules: [// loader的配置{// 处理less资源test: /\.less$/,use: [style-loader, css-loader, less-loader]},{// 处理css资源test: /\.css$/,use: [style-loader, css-loader]},{// 处理图片资源test: /\.(jpg|png|gif)$/,loader: url-loader,options: {limit: 8 * 1024,name: [hash:10].[ext],// 关闭es6模块化esModule: false,outputPath: imgs}},{// 处理html中img资源test: /\.html$/,loader: html-loader},{// 处理其他资源exclude: /\.(html|js|css|less|jpg|png|gif)/,loader: file-loader,options: {name: [hash:10].[ext],outputPath: media}}]},plugins: [// plugins的配置new HtmlWebpackPlugin({template: ./src/index.html})],mode: development,devServer: {contentBase: resolve(__dirname, build),compress: true,port: 3000,open: true,// 开启HMR功能// 当修改了webpack配置新配置要想生效必须重新webpack服务hot: true} }; 运行指令: webpack 5.1.2 优化代码调试 source-map Sourcemap 协议最初由 Google 设计并率先在 Closure Inspector 实现它能够将经过压缩、混淆、合并的代码还原回未打包状态帮助开发者在生产环境中精确定位问题发生的行列位置。 目前很多第三方库在发布的文件中都会同时提供一个 .map 后缀的 Source Map 文件。例如 jQuery。我们可以打开它的 Source Map 文件看一下如下图所示 这是一个 JSON 格式的文件为了更容易阅读我提前对该文件进行了格式化。这个 JSON 里面记录的就是转换后和转换前代码之间的映射关系主要存在以下几个属性 version 是指定所使用的 Source Map 标准版本sources 中记录的是转换前的源文件名称因为有可能出现多个文件打包转换为一个文件的情况所以这里是一个数组names 是源代码中使用的一些成员名称我们都知道一般压缩代码时会将我们开发阶段编写的有意义的变量名替换为一些简短的字符这个属性中记录的就是原始的名称mappings 属性这个属性最为关键它是一个叫作 base64-VLQ 编码的字符串里面记录的信息就是转换后代码中的字符与转换前代码中的字符之间的映射关系 修改配置文件 const { resolve } require(path); const HtmlWebpackPlugin require(html-webpack-plugin);module.exports {entry: [./src/js/index.js, ./src/index.html],output: {filename: js/built.js,path: resolve(__dirname, build)},module: {rules: [// loader的配置{// 处理less资源test: /\.less$/,use: [style-loader, css-loader, less-loader]},{// 处理css资源test: /\.css$/,use: [style-loader, css-loader]},{// 处理图片资源test: /\.(jpg|png|gif)$/,loader: url-loader,options: {limit: 8 * 1024,name: [hash:10].[ext],// 关闭es6模块化esModule: false,outputPath: imgs}},{// 处理html中img资源test: /\.html$/,loader: html-loader},{// 处理其他资源exclude: /\.(html|js|css|less|jpg|png|gif)/,loader: file-loader,options: {name: [hash:10].[ext],outputPath: media}}]},plugins: [// plugins的配置new HtmlWebpackPlugin({template: ./src/index.html})],mode: development,devServer: {contentBase: resolve(__dirname, build),compress: true,port: 3000,open: true,hot: true},devtool: eval-source-map };/*source-map: 一种 提供源代码到构建后代码映射 技术 如果构建后代码出错了通过映射可以追踪源代码错误[inline-|hidden-|eval-][nosources-][cheap-[module-]]source-mapsource-map外部错误代码准确信息 和 源代码的错误位置inline-source-map内联只生成一个内联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. 内联构建速度更快开发环境速度快调试更友好速度快(evalinlinecheap...)eval-cheap-souce-mapeval-source-map调试更友好 souce-mapcheap-module-souce-mapcheap-souce-map-- eval-source-map / eval-cheap-module-souce-map生产环境源代码要不要隐藏? 调试要不要更友好内联会让代码体积变大所以在生产环境不用内联nosources-source-map 全部隐藏hidden-source-map 只隐藏源代码会提示构建后代码错误信息-- source-map / cheap-module-souce-map */ 运行指令: webpack 5.2 生产环境性能优化 5.2.1 优化打包构建速度 oneOf 打包时每个文件都会经过所有 loader 处理虽然因为 test 正则原因实际没有处理上但是都要过一遍。比较慢。所以使用OneOf匹配上一个 loader, 剩下的就不匹配了。开发模式和生产模式都可以用 配置文件 const { resolve } require(path); const MiniCssExtractPlugin require(mini-css-extract-plugin); const OptimizeCssAssetsWebpackPlugin require(optimize-css-assets-webpack-plugin); const HtmlWebpackPlugin require(html-webpack-plugin);// 定义nodejs环境变量决定使用browserslist的哪个环境 process.env.NODE_ENV production;// 复用loader const commonCssLoader [MiniCssExtractPlugin.loader,css-loader,{// 还需要在package.json中定义browserslistloader: postcss-loader,options: {ident: postcss,plugins: () [require(postcss-preset-env)()]}} ];module.exports {entry: ./src/js/index.js,output: {filename: js/built.js,path: resolve(__dirname, build)},module: {rules: [{// 在package.json中eslintConfig -- airbnbtest: /\.js$/,exclude: /node_modules/,// 优先执行enforce: pre,loader: eslint-loader,options: {fix: true}},{// 以下loader只会匹配一个// 注意不能有两个配置处理同一种类型文件oneOf: [{test: /\.css$/,use: [...commonCssLoader]},{test: /\.less$/,use: [...commonCssLoader, less-loader]},/*正常来讲一个文件只能被一个loader处理。当一个文件要被多个loader处理那么一定要指定loader执行的先后顺序先执行eslint 在执行babel*/{test: /\.js$/,exclude: /node_modules/,loader: babel-loader,options: {presets: [[babel/preset-env,{useBuiltIns: usage,corejs: {version: 3},targets: {chrome: 60,firefox: 50}}]]}},{test: /\.(jpg|png|gif)/,loader: url-loader,options: {limit: 8 * 1024,name: [hash:10].[ext],outputPath: imgs,esModule: false}},{test: /\.html$/,loader: html-loader},{exclude: /\.(js|css|less|html|jpg|png|gif)/,loader: file-loader,options: {outputPath: media}}]}]},plugins: [new MiniCssExtractPlugin({filename: css/built.css}),new OptimizeCssAssetsWebpackPlugin(),new HtmlWebpackPlugin({template: ./src/index.html,minify: {collapseWhitespace: true,removeComments: true}})],mode: production }; babel缓存 目标让第二次打包构建速度更快。 在babel-loader配置中添加缓存配置cacheDirectory true const { resolve } require(path); const MiniCssExtractPlugin require(mini-css-extract-plugin); const OptimizeCssAssetsWebpackPlugin require(optimize-css-assets-webpack-plugin); const HtmlWebpackPlugin require(html-webpack-plugin);/*缓存babel缓存cacheDirectory: true-- 让第二次打包构建速度更快文件资源缓存hash: 每次wepack构建时会生成一个唯一的hash值。问题: 因为js和css同时使用一个hash值。如果重新打包会导致所有缓存失效。可能我却只改动一个文件chunkhash根据chunk生成的hash值。如果打包来源于同一个chunk那么hash值就一样问题: js和css的hash值还是一样的因为css是在js中被引入的所以同属于一个chunkcontenthash: 根据文件的内容生成hash值。不同文件hash值一定不一样 -- 让代码上线运行缓存更好使用 */// 定义nodejs环境变量决定使用browserslist的哪个环境 process.env.NODE_ENV production;// 复用loader const commonCssLoader [MiniCssExtractPlugin.loader,css-loader,{// 还需要在package.json中定义browserslistloader: postcss-loader,options: {ident: postcss,plugins: () [require(postcss-preset-env)()]}} ];module.exports {entry: ./src/js/index.js,output: {filename: js/built.[contenthash:10].js,path: resolve(__dirname, build)},module: {rules: [{// 在package.json中eslintConfig -- airbnbtest: /\.js$/,exclude: /node_modules/,// 优先执行enforce: pre,loader: eslint-loader,options: {fix: true}},{// 以下loader只会匹配一个// 注意不能有两个配置处理同一种类型文件oneOf: [{test: /\.css$/,use: [...commonCssLoader]},{test: /\.less$/,use: [...commonCssLoader, less-loader]},/*正常来讲一个文件只能被一个loader处理。当一个文件要被多个loader处理那么一定要指定loader执行的先后顺序先执行eslint 在执行babel*/{test: /\.js$/,exclude: /node_modules/,loader: babel-loader,options: {presets: [[babel/preset-env,{useBuiltIns: usage,corejs: { version: 3 },targets: {chrome: 60,firefox: 50}}]],// 开启babel缓存// 第二次构建时会读取之前的缓存cacheDirectory: true}},{test: /\.(jpg|png|gif)/,loader: url-loader,options: {limit: 8 * 1024,name: [hash:10].[ext],outputPath: imgs,esModule: false}},{test: /\.html$/,loader: html-loader},{exclude: /\.(js|css|less|html|jpg|png|gif)/,loader: file-loader,options: {outputPath: media}}]}]},plugins: [new MiniCssExtractPlugin({filename: css/built.[contenthash:10].css}),new OptimizeCssAssetsWebpackPlugin(),new HtmlWebpackPlugin({template: ./src/index.html,minify: {collapseWhitespace: true,removeComments: true}})],mode: production,devtool: source-map }; 多进程打包 安装 loader 包 npm i thread-loader -D修改配置文件 /*** 多进程打包* 1.下载thread-loader——》cnpm i thread-loader -D* 2.哪个loader需要多进程打包就使用该loader一般给babel-loader使用使用如下:* // 对js进行兼容性处理{test: /\.js$/,exclude: /node_modules/,use: [// 开启多进程打包// 启动进程600ms进程通信也有开销// 只有工作消耗时间比较长才使用多进程打包thread-loader,{loader: babel-loader,options: {presets: [babel/preset-env],plugins: [[babel/plugin-transform-runtime]],//开启缓存第二次构建时只处理发生变化的js文件cacheDirectory:true},},]},*/ const { resolve } require(path); // 引入workbox const WorkboxWebpackPlugin require(workbox-webpack-plugin); const HtmlWebpackPlugin require(html-webpack-plugin); // 将css单独提出文件 const MiniCssExtractPlugin require(mini-css-extract-plugin); // 引入压缩插件 const OptimizeCssAssetsWebpackPlugin require(optimize-css-assets-webpack-plugin); // 将通用的loader抽离出来 // 设置nodejs的环境变量 // process.env.NODE_ENV development; const commonLoaders [MiniCssExtractPlugin.loader, // 使用该loader将js中的css导入到文件中并引入html文件css-loader,{loader: postcss-loader,options: {postcssOptions: {ident: postcss,plugins: [[postcss-preset-env, {}]]}},}, ] module.exports {mode: development,// 单入口// entry: ./src/js/index.js,// 多入口有几个入口就输出几个bundle// entry: {// index: ./src/js/index.js,// test: ./src/js/test.js,// },entry: [babel-polyfill, ./src/js/index.js, ./src/index.html],output: {filename: js/[name][contenthash:10].js,path: resolve(__dirname, build)},module: {rules: [{// 以下loader只会匹配一下提升构建速度// 注意不能有两个loader处理同一个文件oneOf: [// 对js进行兼容性处理{test: /\.js$/,exclude: /node_modules/,use: [thread-loader,{loader: babel-loader,options: {presets: [babel/preset-env],plugins: [[babel/plugin-transform-runtime]],//开启缓存第二次构建时只处理发生变化的js文件cacheDirectory:true},},]},// css文件处理{test: /\.css$/,use: [...commonLoaders],},// less文件处理{test: /\.less$/,use: [...commonLoaders,less-loader],},// image图片处理{test: /\.(jpg|png|gif)$/,type:asset,//解析parser: {//转base64的条件dataUrlCondition: {maxSize: 8 * 1024, // 8kb}},generator:{ //与output.assetModuleFilename是相同的,这个写法引入的时候也会添加好这个路径filename:img/[name][contenthash:10].[ext],//打包后对资源的引入文件命名已经有/img了publicPath:./},},// 处理html中的image资源{test: /\.html$/,loader: html-loader,generator:{ //与output.assetModuleFilename是相同的,这个写法引入的时候也会添加好这个路径filename:img/[name][contenthash:10].[ext],//打包后对资源的引入文件命名已经有/img了publicPath:./},},// 字体图标等其他资源处理{exclude: /\.(html|css|js|jpg|png|gif)$/,type: asset/resource,generator:{ //与output.assetModuleFilename是相同的,这个写法引入的时候也会添加好这个路径filename:otherSource/[name][contenthash:10].[ext],//打包后对资源的引入文件命名已经有/img了publicPath:./},},]},],},plugins: [new HtmlWebpackPlugin({template: ./src/index.html,}),// 使用miniCssExtractPlugin插件将css提取为一个文件new MiniCssExtractPlugin({// 对输出的文件重命名filename: css/built[contenthash:10].css,}),// 调用压缩css插件new OptimizeCssAssetsWebpackPlugin(),// 调用PWA插件new WorkboxWebpackPlugin.GenerateSW({/*** 1.帮助serviceworker快速启动* 2.删除旧的serviceworker* 生成一个serviceworker的配置文件*/clientsClaim: true,skipWaiting: true,}),],devServer: {// 开发服务器项目路径static: resolve(__dirname, build),// 是否开启gzip压缩compress: true,// 端口号port: 3000,// 是否自动打开浏览器open: true,// 打开HMR功能hot: true,},// 开启追踪源代码报错功能devtool: eval-source-map,// 使用代码分割功能/*** 可以将node_modules中的代码单独打包成一个trunk最终输出* 自动分析多入口文件中是否有公共的依赖如果有会打包成一个单独的trunk*/optimization: {splitChunks: {chunks: all}}, } externals externals 配置项提供了阻止将某些 import 的包(package)打包到 bundle 中的功能在运行时(runtime)再从外部获取这些扩展依赖(external dependencies) externals用法 module.exports{configureWebpack:congig {externals:{key: value}} }语法说明 key是第三方依赖库的名称同package.json文件中的dependencies对象的key一样value值可以是字符串、数组、对象。应该是第三方依赖编译打包后生成的js要用CDN引入的js文件文件执行后赋值给window的全局变量名称。 配置文件 const { resolve } require(path); const HtmlWebpackPlugin require(html-webpack-plugin);module.exports {entry: ./src/js/index.js,output: {filename: js/built.js,path: resolve(__dirname, build)},plugins: [new HtmlWebpackPlugin({template: ./src/index.html})],mode: production,externals: {// 拒绝jQuery被打包进来jquery: jQuery} }; dll dll的功能就是对代码分割的一种高级应用将项目中很少变动的依赖先配置出来提前打包在一个文件中然后以script标签的方式注入到index.html文件中接着在build配置中引入打包好的dll配置这样build执行时会跳过dll中已经打包的模块从而加快了build的打包时间 创建webpack.dll.js配置文件配置需要单独打包的js /*** 使用dll技术对某些库第三方库jquery、react、vue...进行单独打包* 当你运行webpack时默认查找webpack.config.js配置文件* 需求需要运行 webpack.dll.js 文件* -- webpack --config webpack.dll.js* 将下面配置的jquery单独打包到dll文件夹下下面需要将打包的jquery重新引入到我们的项目中*/const { resolve } require(path); const webpack require(webpack); module.exports {mode: production,entry: {// 最终打包生成的[name]--jquery// [jquery]--要打包的库是jqueryjquery: [jquery]},// 输出文件output: {filename: [name].js, // 生成的文件名path: resolve(__dirname, dll),library: [name]_[hash], // 打包的库里面向外暴露出去的内容叫什么名字},plugins: [new webpack.DllPlugin({name: [name]_[hash], // 映射库的暴露的内容名称path: resolve(__dirname, dll/manifest.json) // 输出文件路径}),], } 执行命令webpack --config webpack.dll.js修改配置webpack.config.js文件将单独打包的js引入到我们的入口文件 /*** 将webpack.dll插件打包的文件导入到index.js中* 1、配置webpack.DllReferencePlugin告诉webpack哪些包要打包哪些不用打包以及其映射名称* 2、下载安装cnpm i add-asset-html-webpack-plugin -D* 3、配置插件* // 将某个文件打包输出并在html中引入该资源* // 将某个文件打包输出并在html中引入该资源new AddAssetHtmlWebpackPlugin({// 指定要打包的文件路径filepath: resolve(__dirname, dll/jquery.js),// 输出目录outputPath: dll,// html引入的路径publicPath: ./dll,attributes: {nomodule: false,},}),*/ const { resolve } require(path); const HtmlWebpackPlugin require(html-webpack-plugin); const webpack require(webpack); const AddAssetHtmlWebpackPlugin require(add-asset-html-webpack-plugin); module.exports {// 模式mode: development,// 入口文件entry: ./src/index.js,// 输出output: {filename: built.js,path: resolve(__dirname, build),},module: {// 需要使用的loaderrules: []},// 插件plugins: [new HtmlWebpackPlugin({template: ./src/index.html,}),// 告诉webpack哪些库不参与打包并且使用名称也得变new webpack.DllReferencePlugin({manifest: resolve(__dirname, dll/manifest.json)}),// 将某个文件打包输出并在html中引入该资源new AddAssetHtmlWebpackPlugin({// 指定要打包的文件路径filepath: resolve(__dirname, dll/jquery.js),// 输出目录outputPath: dll,// html引入的路径publicPath: ./dll,attributes: {nomodule: false,},}),], } 5.2.2 优化代码运行的性能 缓存(hash-chunkhash-contenthash) 浏览器在多次访问静态资源文件的时候如果该文件已经在本地缓存并且它的名称没有改变那么浏览器会认为它没有被更新便不会去请求服务器而是使用该静态资源的缓存版本。如果某个文件被更改我们希望浏览器应该重新请求它而不是使用缓存版本所以文件被修改后它的名称也应该被改变。 在 webpack 中最后生成的 chunk 文件都是由一个个的 module 编译后组合而成的浏览器请求的 JS文件实际上就是一个个的 chunk 。当我们修改某个 module 后其所属 chunk 打包后的 JS文件名称应该也要发生变化否则浏览器是不会请求最新版本的 JS 文件的 输出文件名 在 webpack 中有 3 种哈希占位符通过它们修改文件名来控制缓存。 hash只要改动某个模块所有 chunk 的 hash 都会被修改不常用chunkhash只要改动某个模块依赖它的 chunk 的 hash 就会被修改常用contenthash只要改动某个模块这个模块的 hash 就会被更改 通常用于被抽离的代码如抽离 css 。如果不抽离该模块contenthash 和 chunkhash 的产生的效果一致 常用webpack3 不支持 contenthash 当 hash 变化后文件名就会变化如果输出文件名使用了上面的 3 中哈希占位符浏览器就会去重新请求对应的资源。 hash 准备测试的文件。 //index1.js console.log(index1.js); import(./async).then((res) {console.log(res); }) //index2.js console.log(index2.js); import(./async).then((res) {console.log(res); }) //async.js console.log(async.js); export default {desc: async.js } //webpack.config.js var HtmlWebpackPlugin require(html-webpack-plugin); var {CleanWebpackPlugin } require(clean-webpack-plugin); module.exports {mode: development,watch: true,entry: {index1: ./index1.js,index2: ./index2.js},output: {publicPath: ,path: __dirname /dist,//配置hashfilename: [name].[hash:16].js},module: {rules: []},plugins: [new CleanWebpackPlugin(),new HtmlWebpackPlugin({template: ./index.html}),] }编译后控制台打印如下。 Asset Size Chunks Chunk Names0.a535734c8f8ddf89.js 515 bytes 0 [emitted] [immutable]index.html 374 bytes [emitted] index1.a535734c8f8ddf89.js 8.54 KiB index1 [emitted] [immutable] index1 index2.a535734c8f8ddf89.js 8.53 KiB index2 [emitted] [immutable] index2可以发现所有 chunk 的 hash 都是 a535734c8f8ddf89 。 修改 async.js、index1.js 或 index2.js 其中的某个文件都将导致所有 chunk 重新构建这里修改async.js 后控制台打印如下。 Asset Size Chunks Chunk Names0.160f75be0b2a9d7a.js 519 bytes 0 [emitted] [immutable]index.html 374 bytes [emitted] index1.160f75be0b2a9d7a.js 8.54 KiB index1 [emitted] [immutable] index1 index2.160f75be0b2a9d7a.js 8.53 KiB index2 [emitted] [immutable] index2可以发现每次的改动都将导致整个项目重新构建。 chunkhash 把 webpack.config.js 中输出配置名称中的 hash 改为 chunkhash 。 //webpack.config.js var HtmlWebpackPlugin require(html-webpack-plugin); var {CleanWebpackPlugin } require(clean-webpack-plugin); module.exports {mode: development,watch: true,entry: {index1: ./index1.js,index2: ./index2.js},output: {publicPath: ,path: __dirname /dist,filename: [name].[chunkhash:16].js},module: {rules: []},plugins: [new CleanWebpackPlugin(),new HtmlWebpackPlugin({template: ./index.html}),] }编译构建后控制台打印如下。 Asset Size Chunks Chunk Names0.ef0a90ca4be41633.js 519 bytes 0 [emitted] [immutable]index.html 374 bytes [emitted] index1.e04fb78630b9ed06.js 8.55 KiB index1 [emitted] [immutable] index1 index2.a82fa8cf316672d3.js 8.54 KiB index2 [emitted] [immutable] index2可以发现每个 chunk 都有自己的专属 hash在修改 index1.js 或 index2.js 的时候也只会导致被修改的文件所属的 chunk 重新构建。 修改 index1.js 后控制台打印如下。 Asset Size Chunks Chunk Namesindex.html 374 bytes [emitted] index1.219644b9fa78ecf2.js 8.53 KiB index1 [emitted] [immutable] index1修改 index2.js 后控制台打印如下。 Asset Size Chunks Chunk Namesindex.html 374 bytes [emitted] index2.2fb396992e95ea30.js 8.53 KiB index2 [emitted] [immutable] index2修改 async.js 后控制台打印如下。 Asset Size Chunks Chunk Names0.ef0a90ca4be41633.js 519 bytes 0 [emitted] [immutable]index.html 374 bytes [emitted] index1.b19fb895cd7844da.js 8.53 KiB index1 [emitted] [immutable] index1 index2.89c07defcd285597.js 8.53 KiB index2 [emitted] [immutable] index2index1.js 和 index2.js 所属的 chunk 重新构建了这是因为 index1 chunk 和 index2 chunk需要懒加载 async.js 而懒加载 async.js 是根据 async.js 所属的 chunk 打包后的文件名来加载的当 async.js 发生变化后它所属的 chunk 打包后的文件名会因为 hash 变化而变化index1 chunk 和 index2 chunk 中懒加载 相关的的路径名称也跟着发生了变化从而导致 index1 chunk 和 index2 chunk 的 hash变化而重新构建。 因为懒加载流程是属于 runtime 安装、加载和连接模块的逻辑部分的代码所以可以将 runtime 部分的代码抽离出来然后再次修改 async.js 发现 index1 chunk 和 index2 chunk 的代码就不会重新构建了。 //webpack.config.js var HtmlWebpackPlugin require(html-webpack-plugin); var {CleanWebpackPlugin } require(clean-webpack-plugin); module.exports {mode: development,watch: true,entry: {index1: ./index1.js,index2: ./index2.js},output: {publicPath: ,path: __dirname /dist,filename: [name].[chunkhash:16].js},module: {rules: []},plugins: [new CleanWebpackPlugin(),new HtmlWebpackPlugin({template: ./index.html}),],optimization: {// single - 表示抽离所有 chunk 公用的 runtime 代码runtimeChunk: single } }编译打包后控制台打印如下。 Asset Size Chunks Chunk Names0.ef0a90ca4be41633.js 519 bytes 0 [emitted] [immutable]index.html 425 bytes [emitted]index1.ce2de40546b020f7.js 545 bytes index1 [emitted] [immutable] index1index2.cf1286e262093666.js 553 bytes index2 [emitted] [immutable] index2 runtime.a0f05e8cde7456ae.js 8.97 KiB runtime [emitted] [immutable] runtime修改 async.js 后控制台打印如下。 Asset Size Chunks Chunk Names0.0f79481d25aeed80.js 523 bytes 0 [emitted] [immutable]index.html 425 bytes [emitted] runtime.fa3fbcea2005af1c.js 8.97 KiB runtime [emitted] [immutable] runtime这下 index1.js 和 index2.js 对应的 chunk 便不会重新构建了因为我们把连接模块的逻辑都抽离出来了改变async.js 会导致 async.js 和 runtime 代码对应的 chunk 重新构建。 contenthash contenthash 只有在抽离某个 module 的时候才会显示它的作用否则它和 chunkhash 的表现一致这里以抽离 css为例。先安装 css-loader 和 mini-css-extract-plugin 。 yarn add css-loader mini-css-extract-plugin -d//index1.css body , html {height: 100%;width: 100%;margin: 0;padding: 0; }//index1.js console.log(index1.js); import(./async).then((res) {console.log(res); }) import ./index1.css;//webpack.config.js var HtmlWebpackPlugin require(html-webpack-plugin); var ProgressPlugin require(webpack).ProgressPlugin; var MiniCssExtractPlugin require(mini-css-extract-plugin); var CleanWebpackPlugin require(clean-webpack-plugin).CleanWebpackPlugin; module.exports {mode: development,watch: true,entry: {index1: ./index1.js,index2: ./index2.js},output: {publicPath: ,path: __dirname /dist,filename: [name].[chunkhash].js},module: {rules: [{test: /\.css$/,use: [MiniCssExtractPlugin.loader, // 抽取css文件的loader不再插入head里css-loader]}]},plugins: [new ProgressPlugin(),new CleanWebpackPlugin(),new MiniCssExtractPlugin({filename: [name].[contenthash].css}),new HtmlWebpackPlugin({template: ./index.html,})],optimization: {// single - 表示抽离所有 chunk 公用的 runtime 代码runtimeChunk: single} }编译打包后控制台打印如下。 Asset Size Chunks Chunk Names0.a84498019577afde7588.js 1.07 KiB 0 [emitted] [immutable]index.html 499 bytes [emitted]index1.470f6e18ca06585dd954.js 1.07 KiB index1 [emitted] [immutable] index1 index1.8db6dca1b242dbbabe70.css 87 bytes index1 [emitted] [immutable] index1index2.82d191b5754b0e2e2ca8.js 537 bytes index2 [emitted] [immutable] index2 runtime.fca50e4fde877e19576a.js 8.98 KiB runtime [emitted] [immutable] runtime修改 index1.js 后控制台打印如下。 Asset Size Chunks Chunk Namesindex.html 499 bytes [emitted] index1.2748748868607facc4a8.js 1.08 KiB index1 [emitted] [immutable] index1index1.css 和 index1.js 都属于 index1 这个 chunk 。当修改 index1.js 后并不会引起indx1.css 重新构建因为 index1.css 不依赖 index1.js 。contenthash 的作用就是当模块自身发生变化的时候才会去重新构建这个模块。 tree shaking Tree-shaking 它的名字来源于通过摇晃shakeJavaScript代码的抽象语法树AST是一种用于优化JavaScript代码的技术主要用于移除未被使用的代码使得最终生成的代码包含应用程序中实际使用的部分。这主要用于减小应用程序的体积提高加载性能。 在前端开发中特别是在使用模块化工具如Webpack、Rollup等构建应用程序时通常会引入许多库和模块。然而应用程序可能只使用了这些库的一小部分功能导致最终生成的代码包含了大量未被使用的代码。Tree-shaking通过静态分析代码来确定哪些代码是可到达的并且被使用的然后去除那些未被使用的部分。这样一来可以显著减小最终部署的代码大小提高应用程序的性能。 Tree Shaking 较早前由 Rich Harris 在 Rollup 中率先实现Webpack 自 2.0 版本开始接入已经成为一种应用广泛的性能优化手段。 1.首先要明确一点Tree Shaking 只支持 ESM 的引入方式不支持 Common JS 的引入方式。 ESM: export importCommon JS: module.exports require 摇树优化是一种在打包编译时移除未使用代码的技术可以显著减少最终打包文件的大小。为了使 Tree Shaking 有效工作你的代码必须基于 ES6 模块的静态结构特性。 静态 vs. 非静态结构 静态结构所有导入和导出都是固定的不依赖于运行时条件。 import a from ./a; import b from ./b; export default a;非静态结构导入或导出依赖于运行时变量或条件语句。 console.log(index.js); const flag Math.random(); if (flag) {module.exports 1; } else {module.exports {}; }if (flag) {require(./a.js); } else {require(./b.js); }准备 Demo unused.js const a 1; const b () {return test.js; }; export {a, b};math.js export function add(a, b) {return a b; } export function sub(a, b) {return a - b; }index.js import {add} from ./math; import * as unused from ./unused;const result add(55, 45); console.log(result);开发环境测试 webpack.config.js开发模式 var HtmlWebpackPlugin require(html-webpack-plugin); var { CleanWebpackPlugin } require(clean-webpack-plugin);module.exports {mode: development,entry: {index: ./index.js,},optimization: {usedExports: true,},output: {publicPath: ,path: __dirname /dist,filename: [name].js},module: {rules: []},plugins: [new CleanWebpackPlugin(),new HtmlWebpackPlugin({template: ./index.html}),] };在开发环境下即使配置了 optimization.usedExports: trueWebPack 只会标记未使用的代码并不会真正删除它们。 生产环境测试 webpack.config.js生产模式 var HtmlWebpackPlugin require(html-webpack-plugin); var { CleanWebpackPlugin } require(clean-webpack-plugin);module.exports {mode: production,entry: {index: ./index.js,},output: {publicPath: ,path: __dirname /dist,filename: [name].js},module: {rules: []},plugins: [new CleanWebpackPlugin(),new HtmlWebpackPlugin({template: ./index.html}),] };在生产模式下WebPack 会对代码进行极致优化未使用的代码会被移除。 sideEffects sideEffects 是指有副作用的代码例如修改全局变量或对象的属性。如果模块中包含这样的代码那么即使该模块的部分导出未被使用整个模块也可能不会被 Tree Shaking 掉。 如果项目中的所有模块都没有副作用可以在 package.json 中设置 sideEffects: false 来加速 Tree Shaking 过程。 如果某些特定的模块具有副作用可以在 package.json 中指定这些模块的路径。 package.json 示例 {name: webpack,version: 1.0.0,main: index.js,license: MIT,scripts: {dev: webpack},sideEffects: [./math.js] }通过以上步骤你可以有效地利用 Tree Shaking 技术来优化你的 JavaScript 应用程序。确保在生产构建中启用适当的 Webpack 设置以获得最佳效果。 code split Webpack 提供了几种不同的方法来实现代码分离以优化加载时间和用户体验。以下是三种主要的代码分离方式 入口起点Entry Points防止重复使用 SplitChunksPlugin 去重和分离 chunk动态导入通过模块的内联函数调用懒加载 1. 入口起点 通过配置多个入口点可以将项目代码分割成多个独立的 chunk。 index.js console.log(index.js);index2.js console.log(index2.js);webpack.config.js const HtmlWebpackPlugin require(html-webpack-plugin); const { CleanWebpackPlugin } require(clean-webpack-plugin);module.exports {mode: development,entry: {index: ./index.js,index2: ./index2.js},output: {publicPath: ,path: __dirname /dist,filename: [name].js},module: {rules: []},plugins: [new CleanWebpackPlugin(),new HtmlWebpackPlugin({ template: ./index.html })] };打包后的目录结构会包含两个独立的 chunk 文件index.js 和 index2.js。 2. 动态导入 利用 JavaScript 的动态 import() 语法可以在运行时按需加载模块从而实现代码的懒加载。 index.js console.log(index.js);import(./async).then((res) {console.log(res); });import(./async2).then((res) {console.log(res); });webpack.config.js const HtmlWebpackPlugin require(html-webpack-plugin); const { CleanWebpackPlugin } require(clean-webpack-plugin);module.exports {mode: development,entry: {index: ./index.js},output: {publicPath: ,path: __dirname /dist,filename: [name].js,chunkFilename: [name].async.js},module: {rules: []},plugins: [new CleanWebpackPlugin(),new HtmlWebpackPlugin({ template: ./index.html })] };打包后的目录结构会包含三个 chunk 文件index.js、0.async.js 和 1.async.js。 3. 防止重复使用 SplitChunksPlugin 当多个 chunk 引入了相同的模块时可以通过 SplitChunksPlugin 来提取这些公共模块避免重复打包。 initial-common.js function initialCommon(a, b) {return a * b; } var res initialCommon(1, 2); console.log(res);async-common.js function asyncCommon(a, b) {return a * b; } var res asyncCommon(1, 2); console.log(res);index1-async1-common.js function index1Async1Common(a, b) {return a * b; } var res index1Async1Common(1, 2); console.log(res);async1.js console.log(async1.js); import ./async-common; import ./index1-async1-common;async2.js console.log(async2.js); import ./async-common;index1.js console.log(index1.js); import ./initial-common; import ./index1-async1-common;import(./async1).then((res) {console.log(res); });import(./async2).then((res) {console.log(res); });index2.js console.log(index2.js); import ./initial-common;webpack.config.js const HtmlWebpackPlugin require(html-webpack-plugin); const { CleanWebpackPlugin } require(clean-webpack-plugin);module.exports {mode: development,entry: {index1: ./index1.js,index2: ./index2.js},output: {publicPath: ,path: __dirname /dist,filename: [name].js,chunkFilename: [name].async.js},module: {rules: []},plugins: [new CleanWebpackPlugin(),new HtmlWebpackPlugin({ template: ./index.html })],optimization: {splitChunks: {chunks: all,minSize: 0,minChunks: 2,automaticNameDelimiter: ~,cacheGroups: {vendors: {test: /[\\/]node_modules[\\/]/,priority: -10},common: {priority: -20,reuseExistingChunk: true}}}} };打包后的目录结构将会根据配置生成相应的 chunk 文件并且共享的代码会被提取到单独的文件中例如 common~index1~index2.async.js 和 0.async.js 等。 懒加载/预加载 1. 基本配置 首先我们需要一个基本的 Webpack 配置文件这里使用单入口形式 const path require(path); const HtmlWebpackPlugin require(html-webpack-plugin);module.exports {mode: production,entry: ./src/js/index.js, // 单入口output: {filename: js/[name].[contenthash:10].js,path: path.resolve(__dirname, build),},plugins: [new HtmlWebpackPlugin({template: ./src/index.html, // 引用 HTML 模板minify: { // 压缩 HTMLcollapseInlineTagWhitespace: true,removeComments: true,}}),],optimization: {splitChunks: {chunks: all // 可以将 node_modules 中的模块单独打包成一个 chunk}},devtool: source-map, };2. 懒加载 (Lazy Loading) 懒加载是一种按需加载代码的技术它允许你只在需要时才加载特定的 JavaScript 模块。这可以显著减少初始加载时间并提高应用性能。 2.1 动态导入语法 Webpack 支持 ES6 的 import() 语法来进行动态导入。这种语法返回一个 Promise可以用来异步加载模块。 示例代码 // src/js/index.js console.log(index.js 被加载了);document.getElementById(btn).onclick async function() {const { mul } await import(/* webpackChunkName: test */ ./test);console.log(mul(4, 5)); };懒加载模块 (src/js/test.js) export function mul(a, b) {return a * b; }HTML 文件 (src/index.html) !DOCTYPE html html langen headmeta charsetUTF-8meta nameviewport contentwidthdevice-width, initial-scale1.0titleLazy Loading Example/title /head bodyh1Lazy Loading with Webpack/h1button idbtnLoad Test Module/button /body /html通过上述配置当你点击按钮时test.js 将会被按需加载而不是在页面初始化时就加载。 3. 预加载 (Preloading) 预加载是一种在后台提前加载资源的技术可以在用户真正需要这些资源之前就开始加载它们。这样可以减少用户等待的时间提高用户体验。 3.1 使用 webpackPrefetch 你可以通过在动态导入语句中添加 webpackPrefetch: true 来实现预加载。 示例代码 // src/js/index.js console.log(index.js 被加载了);document.getElementById(btn).onclick async function() {const { mul } await import(/* webpackChunkName: test, webpackPrefetch: true */ ./test);console.log(mul(4, 5)); };预加载模块 (src/js/test.js) export function mul(a, b) {return a * b; }HTML 文件 (src/index.html) !DOCTYPE html html langen headmeta charsetUTF-8meta nameviewport contentwidthdevice-width, initial-scale1.0titlePreloading Example/title /head bodyh1Preloading with Webpack/h1button idbtnLoad Test Module/button /body /html在上述配置中import(/* webpackChunkName: test, webpackPrefetch: true */ ./test) 会生成一个预加载的 link 标签以便在浏览器空闲时预先加载 test.js。 4. 区别与总结 懒加载通过动态导入 import() 语法在需要时异步加载模块。预加载通过 webpackPrefetch: true 注释在浏览器空闲时提前加载可能需要的资源。 区别 预加载会在使用之前提前请求 JS 文件但不会立即调用懒加载是当文件被需要时才会请求。正常加载被认为是并行加载同一时间加载多个文件但可能没有人使用所以提倡懒加载。懒加载中的预加载会在其他文件加载完毕后在浏览器空闲的时候进行预加载以备打算使用该模块的人等待时间过长。 通过合理使用懒加载和预加载你可以显著提升应用的加载性能和用户体验。确保在实际项目中根据具体需求选择合适的加载方式并进行适当的配置。 PWA渐进式 Web 应用配置详解 PWA即渐进式 Web 应用是一种利用现代 Web 技术来提供类似原生应用体验的 Web 应用。它支持离线访问、推送通知以及后台同步等功能极大地增强了用户体验。本文将介绍如何使用 Webpack 配置一个 PWA 项目并通过示例代码展示其核心功能。 1. Webpack 配置 为了构建一个 PWA我们需要在 Webpack 配置中添加一些插件和加载器来处理 CSS、JavaScript 以及其他资源文件。此外我们还需要使用 workbox-webpack-plugin 来生成 Service Worker 文件以便实现离线缓存和其他 PWA 功能。 基本配置 const path require(path); const HtmlWebpackPlugin require(html-webpack-plugin); // HTML 模板 const MiniCssExtractPlugin require(mini-css-extract-plugin); // 提取 CSS const OptimizeCssAssetsWebpackPlugin require(optimize-css-assets-webpack-plugin); // 压缩 CSS const WorkboxWebpackPlugin require(workbox-webpack-plugin); // 使用 PWA process.env.NODE_ENV production;// 复用 CSS 的 loader let commonCssLoader [{loader: MiniCssExtractPlugin.loader,options: {publicPath: ../, // 避免 CSS 中的路径引入错误}},css-loader,{loader: postcss-loader,options: {ident: postcss,plugins: () [require(postcss-preset-env)()]}} ];module.exports {mode: production, // 生产模式entry: ./src/js/index.js,output: {filename: built.[contenthash:10].js,path: path.resolve(__dirname, build)},module: {rules: [// CSS 和 Less{test: /\.css$/,use: [...commonCssLoader]},{test: /\.less$/,use: [...commonCssLoader, less-loader]},// JavaScript 兼容性处理{test: /\.js$/,exclude: /node_modules/,loader: babel-loader,options: {presets: [[babel/preset-env,{useBuiltIns: usage,corejs: { version: 3 },targets: {chrome: 60,firefox: 60,ie: 9,safari: 10,edge: 17}}]],cacheDirectory: true}},// 图片处理{test: /\.(jpg|png|gif)$/,loader: url-loader,options: {limit: 8 * 1024,name: [contenthash:10].[ext],outputPath: imgs,esModule: false}},// HTML 处理{test: /\.html$/,loader: html-loader},// 其他资源处理{exclude: /\.(js|html|css|less|json|jpg|png|gif)$/,loader: file-loader,options: {outputPath: media}}]},plugins: [new HtmlWebpackPlugin({template: ./src/index.html, // 引用 HTML 模板minify: { // 压缩 HTMLcollapseInlineTagWhitespace: true,removeComments: true}}),new MiniCssExtractPlugin({filename: css/built.[contenthash:10].css // 设置 CSS 输出}),new OptimizeCssAssetsWebpackPlugin(), // 压缩 CSS 插件new WorkboxWebpackPlugin.GenerateSW({ // 生成 Service WorkerclientsClaim: true,skipWaiting: true})] };2. 主入口文件 (index.js) 主入口文件需要导入样式和执行必要的逻辑并且注册 Service Worker 以启用 PWA 特性。 import ../css/c.less; import ../css/a.css; import ../css/b.css; import ../css/iconfont.css; import ../css/index.css; import { mul } from ./test;const add (x, y) x y; new Promise((resolve) {console.log(promise);setTimeout(() {console.log(timeout);resolve();}, 0); }).then(() {console.log(p_end); }); console.log(add(2, 3));console.log(mul(3, 3));// 注册 Service Worker if (serviceWorker in navigator) {window.addEventListener(load, () {navigator.serviceWorker.register(/service-worker.js).then((res) {console.log(注册 service-worker 成功, res);}).catch((e) {console.log(e);});}); }3. ESLint 配置 如果你希望 ESLint 支持浏览器全局变量可以在 package.json 中添加或修改 eslintConfig 字段 {eslintConfig: {env: {browser: true,es6: true},extends: eslint:recommended,rules: {// 自定义规则}} }4. 离线访问验证 当你的 PWA 应用已经部署并且 Service Worker 已经注册后你可以尝试断开网络连接并刷新页面检查是否仍然可以正常加载。如果一切设置正确你应该能看到应用依然可用并且控制台会显示从 Service Worker 缓存中加载资源的信息。
http://www.pierceye.com/news/236389/

相关文章:

  • 织梦程序来搭建网站人才招聘网最新招聘信息
  • 网站建设 客户定位支付网站建设费会计分录
  • 深圳网站设计工作室广告公司名字 三个字
  • 长沙门户网站广告网站设计公司
  • 余姚网站建设的公司wordpress 开发文档
  • 怎么建设一个微信网站莱芜金点子最新招工信息
  • 石家庄网站排名优化wordpress修改布局
  • 景安服务器管理助手如何备份网站国外做图标网站
  • 网站轮播怎么做石家庄网站建设规划
  • 免费软件网站下载深圳网站开发哪个公司好
  • 建设项目验收网站公示内网门户网站建设方案
  • 滨海做网站哪家最好宝安附近做网站公司
  • 详情页的五大模块东莞网站优化科技有限公司
  • 南阳建设网站哪家好昆明网站服务
  • 大潮建设集团有限公司 网站网站改版策划方案
  • 网站开发心路历程烟台网站建设薇企汇互联见效付款
  • 企业网站的制作周期wordpress添加数据库表
  • 广告推广营销网站网站买空间的价格
  • 转转假网站怎么做linux建设视频网站
  • 伍佰亿搜索引擎网站系统wordpress 增加备案
  • 韩国做游戏的电影 迅雷下载网站有哪些网络营销方式文献
  • 大学生兼职网站的融资方案龙华网站建设设计制作公司
  • 青之峰网站建设哪家好用什么l软件做网站了
  • 免费建站资源怎么编写app软件
  • 机关网站建设建议云南响应式网站建设
  • 对网站开发语言的统计杭州网站设计公司有哪些
  • 不会代码 怎么做网站兴义网络推广
  • 综合电子商务型企业网站怎么做网站的网盘
  • ucenter使用自己做的网站房地产新闻时事热点
  • 企业网站备案 过户电商运营视频教程