# fed-e-task-webpack **Repository Path**: frontend_site/fed-e-task-webpack ## Basic Information - **Project Name**: fed-e-task-webpack - **Description**: 从零配置webpack参数实践 - **Primary Language**: JavaScript - **License**: ISC - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2020-06-15 - **Last Updated**: 2020-12-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Webpack_Options ## 1. sourceMap 源代码与打包后的代码的映射关系,通过sourceMap定位到源代码。 在dev模式中,默认开启,关闭的话 可以在配置⽂件⾥。 devtool的介绍:https://webpack.js.org/configuration/devtool#devtool ```javascript devtool:"none" eval:速度最快,使⽤eval包裹模块代码, source-map: 产⽣ .map ⽂件 cheap:较快,不包含列信息 Module:第三⽅模块,包含loader的sourcemap(⽐如jsx to js ,babel的sourcemap) inline: 将 .map 作为DataURI嵌⼊,不单独⽣成 .map ⽂件 //配置推荐: devtool:"cheap-module-eval-source-map",// 开发环境配置 //线上不推荐开启 devtool:"cheap-module-source-map", // 线上⽣成配置 ``` ## 2. context 基础目录,**绝对路径**,用于从配置中解析入口起点, 不设置可能导致报错 ```js context: path.resolve(__dirname, "app") ``` 默认使用当前目录,但是推荐在配置中传递一个值。 ## 3. Babel处理ES6+ Babel是JavaScript编译器,能将ES6代码转换成ES5代码,让我们开发过程 中放⼼使⽤JS新特性⽽不⽤担⼼兼容性问题。并且还可以通过插件机制根 据需求灵活的扩展。 Babel在执⾏编译的过程中,会从项⽬根⽬录下的 .babelrc⽂件中 读取配置。没有该⽂件会从loader的options读取配置。 ### 1. Babel 安装依赖: ```javascript npm i babel-loader @babel/core @babel/preset-env -D //.babel-loader是webpack 与 babel的通信桥梁,不会做把es6转成es5的⼯作,这部分⼯作需要⽤到@babel/preset-env来做 // @babel/preset-env⾥包含了es,6,7,8转es5的转换规则 ``` 配置信息: ```javascript { test: /\.js$/, exclude: /node_modules/, use: { loader: "babel-loader", options: { presets: ["@babel/preset-env"] } } } ``` ### 2. @babel/polyfill **通过上⾯的⼏步 还不够,默认的Babel只⽀持let等⼀些基础的特性转换, Promise等⼀些还有转换过来,这时候需要借助@babel/polyfill,把es的新特 性都装进来,来弥补低版本浏览器中缺失的特性。** 以全局变量的⽅式注⼊进来的。windows.Promise,它会造成全局对象的污染。 ```javascript npm install --save @babel/polyfill ``` 配置信息: ```javascript // index.js 顶部 import "@babel/polyfill"; // 以全局变量的⽅式注⼊进来的。windows.Promise,它会造成全局对象的污染。 // 或者在webpack.config.js的配置: entry: { // 字符串、数组、对象、函数 app: ['@babel/polyfill','./src/index.js'] }, ``` ### 3. 按需加载,减少冗余 **因为polyfill默认会把所有特性注⼊进 来,假如想⽤到的es6+,才会注⼊,没⽤到的不注⼊,从⽽减少打包的体积** ```javascript // 1. 配置 - "useBuiltIns": "usage" //按需注⼊ options: { "presets": [ [ "@babel/preset-env", { "targets": { "browsers": [ "> 1%", "last 2 version" ] //具体可以去babel-preset里面查看 }, "corejs": 2, //新版本需要指定核⼼库版本 "useBuiltIns": "usage" //按需注⼊ } ] // 指定哪些语法编译 ] } // 2. 删除/注释 // 删除/注释-全局引用注入@babel/polyfill ``` ### 4. babel-runtime ```javascript npm install --save-dev @babel/plugin-transform-runtime npm install --save @babel/runtime // babel-plugin-transform-runtime,它就可以帮助我们去避免手动引入 import的痛苦,并且它还做了公用方法的抽离 // babel-polyfill和babel-runtime就是为了解决新的API与这种全局对象或全局对象方法不足的问题,因此可以使用这两个插件可以转换的 ``` **babel-polyfill:** 它是通过向全局对象和内置对象的prototype上添加方法来实现的。但是缺点就是会造成全局空间污染。 **babel-runtime:** 它不会污染全局对象和内置对象的原型,而且可以减少不必要的代码。 ```javascript // 配置.babelrc, 注释之前的presets, 添加plugins { "plugins": [ // babel-runtime [ "@babel/plugin-transform-runtime", { "helpers": true, "regenerator": true, "useESModules": false, "absoluteRuntime": false } ] ], // "presets": [ // babel-polyfill // [ // "@babel/preset-env", // { // "targets": { // "browsers": [ // "> 1%", // "last 2 version" // ] //具体可以去babel-preset里面查看 // }, // "corejs": 2, //新版本需要指定核⼼库版本 // "useBuiltIns": "usage" //按需注⼊ // } // ] // 指定哪些语法编译 // ] } ``` ## 4. 页面展示 ```javascript npm install react react-dom --save // 需要安装-使用 Babel REPL npm install --save-dev @babel/preset-react // 配置.babelrc { "presets": [ [ "@babel/preset-react" ] // 指定哪些语法编译 ], "plugins": [ // babel-runtime [ "@babel/plugin-transform-runtime", { "helpers": true, "regenerator": true, "useESModules": false, "absoluteRuntime": false } ] ] } ``` ## 5. loader ### 1. css处理 ```javascript npm install css-loader style-loader less less-loader -D // 使⽤postcss为样式⾃动补⻬浏览器前缀 npm i postcss-loader autoprefixer -D // 新建并配置postcss.config.js module.exports = { plugins: [ require("autoprefixer")({ overrideBrowserslist: ["last 2 versions", ">1%"] }) ] }; ``` ### 2. 抽离css ```javascript npm install mini-css-extract-plugin -D const MiniCssExtractPlugin = require("mini-css-extractplugin"); // "style-loader", // 不再需要style-loader,⽤ MiniCssExtractPlugin.loader代替 new MiniCssExtractPlugin({ filename: "css/[name]_[contenthash:6].css", chunkFilename: "[id].css" }) ``` ### 3. 压缩css ```javascript npm install cssnano -D npm i optimize-css-assets-webpack-plugin -D const OptimizeCSSAssetsPlugin = require("optimize-css-assetswebpack-plugin"); new OptimizeCSSAssetsPlugin({ cssProcessor: require("cssnano"), //引⼊cssnano配置压缩选项 cssProcessorOptions: { discardComments: { removeAll: true } } }) ``` ### 4. tree Shaking webpack2.x开始⽀持 tree shaking概念,顾名思义,"摇树",清除⽆⽤ css,js(Dead Code) #### 1. Css tree shaking ```javascript npm i glob-all purify-css purifycss-webpack --save-dev const PurifyCSS = require('purifycss-webpack') const glob = require('glob-all') plugins:[ // 清除⽆⽤ css new PurifyCSS({ paths: glob.sync([ // 要做 CSS Tree Shaking 的路径⽂件 path.resolve(__dirname, './src/*.html'), // 请注意,同样需要对.html进⾏tree shaking path.resolve(__dirname, './src/*.js') ]) }) ] ``` #### 2. JS tree shaking 只⽀持import⽅式引⼊,不⽀持commonjs的⽅式引⼊ ⽣产模式不需要配置,默认开启 ### 5. 代码分割 其实code Splitting概念 与 webpack并没有直接的关系,只不过webpack中 提供了⼀种更加⽅便的⽅法供我们实现代码分割 基于https://webpack.js.org/plugins/split-chunks-plugin/ ```javascript // 修改webpack配置文件 optimization: { splitChunks: { chunks: 'all', }, cacheGroups: {//缓存组 vendors: { test: /[\\/]node_modules[\\/]/, name:"vendor", // 要缓存的 分隔出来的 chunk 名称 priority: -10//缓存组优先级 数字越⼤,优先级越⾼ }, other:{ chunks: "initial", // 必须三选⼀: "initial" | "all" | "async"(默认就是async) test: /react|lodash/, // 正则规则验证,如果符合就提取 name:"other", minSize: 30000, minChunks: 1 } } }, // chunkhash只能用在生产环境不能用在开发环境 ``` ### 6. DllPlugin 动态链接库,建议使用在开发模式下,主要是用来优化构建速度的; 生产模式推荐代码分割; ```javascript // webpack.dll.js /** * @desc 静态公共资源打包配置 */ const path = require('path'); const { DllPlugin } = require('webpack') module.exports = { entry: ["react", "react-dom"], output: { path: path.resolve(__dirname, '..', 'dll'), filename: 'react.dll.js', library: 'react' // 挂载到该变量名的变量下 }, plugins: [ new DllPlugin({ // manifest.json⽂件的输出位置 path: path.resolve(__dirname, '..', 'dll/reactmanifest.json'), // 定义打包的公共vendor⽂件对外暴露的函数名 name: 'react' // 必须与library的名称一致 }) ] } ``` 需要再安装⼀个依赖 npm i add-asset-html-webpack-plugin ,它 会将我们打包后的 dll.js ⽂件注⼊到我们⽣成的 index.html 中.在 webpack.base.config.js ⽂件中进⾏更改 ```javascript npm i add-asset-html-webpack-plugin -D // webpack.dev.js const AddAssetHtmlWebpackPlugin = require('add-asset-html-webpack-plugin'); new AddAssetHtmlWebpackPlugin({ filepath: path.resolve(__dirname, '../dll/react.dll.js') // 对 应的 dll ⽂件路径 }), new webpack.DllReferencePlugin({ manifest: path.resolve(__dirname, '..', 'dll/reactmanifest.json') }), ```