Webpack4.0笔记
#
webpack 究竟是什么?import 与 export default 是 ES Moudule 模块引入规范 (浏览器不认识 webpack 认识)
Node.js 中用的是 CommonJS 模块引入规范 ( require('./index.js') 与 modules.exports)
webpack 是模块打包工具 (import 引入的内容就是模块)
#
Webpack 的正确安装方式先安装 node.js 环境
创建一个 node 项目,在项目目录下执行(会生成 package.json 文件) npm init
全局安装 webpack 和 webpack-cli (不推荐,推荐在项目内安装 webpack) npm install webpack webpack-cli -g npm uninstall webpack webpack-cli -g (全局删除)
项目目录下安装 webpack 和 webpack-cli(使得在命令行中可以使用 webpack 这个打包命令) npm install webpack webpack-cli -D npx webpack -v 可以查看在当前目录下 webpack 是否在项目中安装好(因为直接 webpack -v 会在全局中使用这个命令是找不到的)
#
使用 Webpack 的配置文件 (webpack.config.js)- 在项目目录下创建 webpack.config.js
#
Webpack 的核心概念#
什么是 loader- loader 执行顺序是从右到左 (倒序)
#
使用 Loader 打包静态资源(图片篇)image-compressor---https://www.jianshu.com/p/3ce3e3865ae2
一个简单的 JavaScript 图像压缩器。使用浏览器的原生 canvas.toBlob API 做的压缩工作。一般使用此压缩是在客户端图像文件上传之前。
- npm install image-compressor.js // 注意是 image-compressor.js 不是 image-compressor 那是另一个包
#
使用 Loader 打包静态资源(样式篇)#
postcss-loader 使用方法如下:(给 css 属性添加厂商前缀的 loader)#
打包字体文件#
使用 plugins 让打包更便捷 (plugin 可以在 webpack 运行到某个时刻的时候,帮你做一些事情)#
Html-Webpack-Plugin(自动生成一个 html 文件 --index.html) 和 Clean-Webpack-Plugin(打包之前清除 dist)#
基本用法HtmlWebpackPlugin 插件文档: https://github.com/jantimon/html-webpack-plugin#configuration npm install --save-dev html-webpack-plugin
npm install clean-webpack-plugin -D
#
Entry 与 Output 的基础配置#
多个入口文件 和 publicPath(JS 上传到 CDN 使用)在编译时不知道最终输出文件的 publicPath 的情况下,publicPath 可以留空,并且在入口起点文件运行时动态设置。如果你在编译时不知道 publicPath,你可以先忽略它,并且在入口起点设置webpack_public_path
#
Source-Map(映射关系) 的配置 (devtool)为了更容易地追踪错误和警告,JavaScript 提供了 source map 功能,将编译后的代码映射回原始源代码。如果一个错误来自于 a/b/c.js 其中一个,source map 就会明确的告诉你。
#
devtool 此选项控制是否生成,以及如何生成 source map , 不同的值会明显影响到构建 (build) 和重新构建 (rebuild) 的速度。https://www.webpackjs.com/configuration/devtool/
开发环境推荐: cheap-module-eval-source-map
生成环境推荐: cheap-module-source-map 没有列映射 (column mapping) 的 source map,将 loader source map 简化为每行一个映射 (mapping)
- 只要有 source-map 就有一个 map 映射文件
- 加 inline 就会把 map 映射文件合并到输出文件里面去
- 加 cheap 只提示哪一行出错 不提示那一列 只负责业务代码的错误 loader 的报错不管
- 加 module 就会负责 loader 的错误
- 加 eval 会通过 eval 的方式对代码执行 eval() 函数可计算某个字符串,并执行其中的的 JavaScript 代码。
#
使用 Webpack-Dev-Server 提升开发效率(可以帮助你在代码发生变化后自动编译代码)#
基本使用https://www.webpackjs.com/configuration/dev-server/
- npm install webpack-dev-server -D
- npm scripts 里面写入 start 命令为 webpack-dev-server
#
Hot Module Replacement 热模块更新#
基本使用#
module.hot.accept#
使用 Babel 处理 ES6 语法#
基本使用https://www.babeljs.cn/setup#installation
npm install --save-dev babel-loader @babel/core (连接 webpack 和 js 文件)
npm install @babel/preset-env --save-dev (转换 es6 的代码 const 之类的)
npm install --save @babel/polyfill (转换一些 es6 的方法 Promise 之类的)
在入口文件引入 import "@babel/polyfill"; (会让包变得很大 需要配置按需引入 polyfill 看第 5 条 )
配置 useBuiltIns 设置 polyfill 只转换用到的方法 代码如下 (配置按需引入 polyfill)
Babel 的 options 太繁长,可以不写 去创建一个 .babelr 文件写入配置选项
#
polyfill 其他注意事项 (写库 第三方组件时 polyfill 的配置)transform-runtimehttps://www.babeljs.cn/docs/babel-plugin-transform-runtime
polyfill 可能会产生全局变量,污染全局的代码,如果写 ui 组件库之类的第三方模块就要用其他的方法打包
npm install --save-dev @babel/plugin-transform-runtime
npm install --save @babel/runtime
#
Webpack 实现对 React 框架代码的打包#
基本使用https://www.babeljs.cn/docs/babel-preset-react
npm install --save-dev @babel/preset-react
配置代码到。babelr 文件
#
Webpack 的高级概念#
Tree Shaking (移除 JavaScript 上下文中的未引用代码 (export 了却并未 import 的代码))你可以将应用程序想象成一棵树。绿色表示实际用到的源码和 library,是树上活的树叶。灰色表示无用的代码,是秋天树上枯萎的树叶。为了除去死去的树叶,你必须摇动这棵树,使它们落下。
实际上 Tree Shaking 发现引入了一个模块就会去看这个模块导出了什么,引入了什么。没引用的就会被删除
https://www.webpackjs.com/guides/tree-shaking/
#
基本使用为了学会使用 tree shaking,你必须……
使用 ES2015 模块语法(即 import 和 export)。 只支持 ES 语法 CommonJS 引入是不支持的
在项目 package.json 文件中,添加一个 "sideEffects" 入口。(请看注意事项 -- 副作用举例)
引入一个能够删除未引用代码 (dead code) 的压缩工具 (minifier)(例如 UglifyJSPlugin,BabelMinifyWebpackPlugin,ClosureCompilerPlugin)
#
Develoment 和 Production 模式的区分打包 (遵循逻辑分离,我们通常建议为每个环境编写彼此独立的 webpack 配置。)把 webpack.config.js 分为 webpack.common.js 和 webpack.dev.js 和 webpack.prod.js
遵循不重复原则 (Don't repeat yourself - DRY),保留一个“通用”配置。 为了将这些配置合并在一起,我们将使用一个名为 webpack-merge(配置合并)的工具。
npm scripts 里面把 strat 指令加上指定 webpack 配置文件语句 (--config webpack.dev.js) npm run build 同理
#
webpack-merge(配置合并)的使用npm install --save-dev webpack-merge
#
DefinePlugin (指定环境)https://www.webpackjs.com/guides/production/#%E6%8C%87%E5%AE%9A%E7%8E%AF%E5%A2%83
#
Webpack 和 Code Splitting(代码拆分)有三种常用的代码分离方法:
入口起点:使用 entry 配置手动地分离代码。
防止重复:使用 CommonsChunkPlugin 去重和分离 chunk。
动态导入:通过模块的内联函数调用来分离代码。
#
防止重复 (prevent duplication) CommonsChunkPlugin 已被替代webpack 作代码分割,异步代码不用管,同步代码只要配置 optimization 即可
ExtractTextPlugin: 用于将 CSS 从主应用程序中分离。
bundle-loader: 用于分离代码和延迟加载生成的 bundle。
promise-loader: 类似于 bundle-loader ,但是使用的是 promises。
CommonsChunkPlugin 插件还可以通过使用显式的 vendor chunks 功能,从应用程序代码中分离 vendor 模块。
#
SplitChunksPlugin 配置参数详解#
Lazy Loading 懒加载,Chunk 是什么?每个打包的 JS 文件都是一个 Chunk (minChunks)
#
打包分析 -Preloading, Prefetching(analyse/ 分析) https://github.com/webpack/analyse
首先要生成打包过程的描述文件 通过 script--dev-- 添加 instructions 指令,打包之后就会把 json 格式的项目描述文件放到 stats.json
http://webpack.github.com/analyse 进入这个工具网站可以把描述文件上传进行工具化分析(官方的比较简单,下面也有一些 webpack 官方推荐的插件,功能比较全)
如果我们以分离代码作为开始,那么就以检查模块作为结束,分析输出结果是很有用处的。官方分析工具 是一个好的初始选择。下面是一些社区支持 (community-supported) 的可选工具:
https://www.webpackjs.com/guides/code-splitting/#bundle-%E5%88%86%E6%9E%90-bundle-analysis-
webpack-chart: webpack 数据交互饼图。
webpack-visualizer: 可视化并分析你的 bundle,检查哪些模块占用空间,哪些可能是重复使用的。(常用!!!)
webpack-bundle-analyzer: 一款分析 bundle 内容的插件及 CLI 工具,以便捷的、交互式、可缩放的树状图形式展现给用户。
#
css 文件的代码分割- 注意 tree shaking 所以一般要设置"sideEffects": ["*.css"]
#
Webpack 与浏览器缓存 ( Caching )[contenthash] -- 根据 content 内容产生的一个哈希字符串 content 不变哈希值不变
webpack 把 业务代码 和 引用库的关联代码 叫 manifest 老版本 webpack 中 业务代码和库的 js 中都有 manifest (所以哪怕代码内容不变 关联可能变了哈希值也会变),加一个 runtimeChunk 就会把关联代码单独拿出来放在 runtime.js 中
#
Shimming(垫片)#
环境变量的使用方法利用全局变量 了解概念即可
#
Webpack 实战配置案例讲解#
Library(组件库 库的打包) 的打包#
怎么给别人用- 注册一个 npm 账号
- npm publish(库的名字是不能相同的)
- 别人 npm install library 就可以使用了
#
PWA(渐进式 Web APP) 的打包配置其目的是通过各种 Web 技术实现与原生 App 相近的用户体验
- webpack 安装插件 WorkboxPlugin
- 在业务代码中应用 serviceWorker
#
TypeScript 的打包配置npm install ts-loader
配置一个 tsconfig.json
#
我们引入一个库 希望这个库的方法能够也拥有类型检查- npm install @type/lodash // 安装之后就可以识别 lodash 的函数要用那些参数
#
怎么搜索安装 库对应的类型文件 (其他类型文件)- 打开 github 搜索 DefinitelyTyped
- 找到 TypeSearch-🔗链接 可以在里面搜索 https://www.typescriptlang.org/dt/search/
#
使用 WebpackDevServer 实现请求转发https://webpack.js.org/configuration/dev-server/#root
#
WebpackDevServer 解决单页面应用路由问题#
EsLint 在 Webpack 中的配置#
使用 EsLintnpx eslint --init // 安装 EsLint
EsLint 配置文件:.eslintrc.js
- VSCode 安装 ESLint 插件 根据错误提示手动修改代码规范
#
把 ESLint 结合在 Webpack 中- npm install eslint-loader --save-dev
#
eslint-loader 已不推荐使用。请使用 eslint-webpack-pluginhttps://github.com/webpack-contrib/eslint-webpack-plugin
- npm install eslint-webpack-plugin --save-dev
#
webpack 性能优化#
打包速度#
1. 跟上技术的迭代 (Node,Npm,Yarn)#
2. 在尽可能少的模块上应用 Loader (比如 include:path.resolve(__dirname,'../src') 只在 src 下应用 babel-loaders)#
3. Plugin 尽可能精简并确保可靠#
4. resolve 参数合理配置#
5. 使用 DIIPlugin 提高打包速度 (第三方模块只打包一次)#
6. 控制包文件大小#
7. thread-loader,padrallel-webpack,happypack 多进程打包项目变的庞大,文件很多的情况下,采取多进程打包 如果小项目,文件不多,无需开启多进程打包,反而会变慢,因为开启进程是需要花费时间的
多进程打包:
- 安装 thread-loader npm i thread-loader -D
#
8. 合理使用 sourceMap#
9. 结合 stats 分析打包结果#
10. 开发环境内存编译 无用插件剔除#
11. 使用 ParallelUglifyPlugin 多进程并行压缩 JS 代码#
总结~小技巧:手摸手 webpack 性能优化技巧: https://juejin.cn/post/6844903652956569608#heading-14 https://juejin.im/post/5b5d6d6f6fb9a04fea58aabc
它内置的代码分割策略是这样的:
新的 chunk 是否被共享或者是来自 node_modules 的模块
新的 chunk 体积在压缩之前是否大于 30kb
按需加载 chunk 的并发请求数量小于等于 5 个(太多了就不分了 不然 http 请求次数太多)
页面初始加载时的并发请求数量小于等于 3 个(太多了就不分了 不然 http 请求次数太多)
它内置的代码分割策略很好很不错,但有些场景下这些规则可能就显得不怎么合理了。比如我有一个管理后台,它大部分的页面都是表单和 Table,我使用了一个第三方 table 组件(比如 element table),几乎后台每个页面都需要它,但它的体积也就 15kb,不具备单独拆包的标准,它就这样被打包到每个页面的 bundle 中了,这就很浪费资源了。这种情况下建议把大部分页面能共用的组件单独抽出来,合并成一个 component-vendor.js 的包(后面会介绍)
#
拆包策略:基础类库 chunk-libs
UI 组件库 chunk-elementUI
自定义共用组件 / 函数 chunk-commons
低频组件 chunk-eachrts/chunk-xlsx 等
业务代码 lazy-loading xxxx.js
#
持久化缓存:使用 runtimeChunk 提取 manifest,使用 script-ext-html-webpack-plugin 等插件内联到 index.html 减少请求
使用 HashedModuleIdsPlugin 固定 moduleId
使用 NamedChunkPlugin 结合自定义 nameResolver 来固定 chunkId
#
多页面打包配置#
Webpack 底层原理及脚手架工具分析#
如何编写一个 Loaderhttps://www.webpackjs.com/api/loaders/ 创建一个文件夹 loaders -- 创建一个 replaceLoader.js 文件
#
如何编写一个 Pluginhttps://www.webpackjs.com/api/plugins/ 创建一个文件夹 plugins -- 创建一个 copyright-webapck-plugin.js 文件
#
快速查看 compilation 参数的内容#
Bundler 源码编写 看 bundler/bundler.js 文件创建一个文件夹 bundler 创建 bundler/src/index.js bundler/src/message.js bundler/src/word.js 文件
创建一个 bundler/bundler.js 文件 并安装 node.js
npm install cli-highlight (高亮显示代码的工具 打包出来的代码在控制台中可以高亮查看)
npm install @babel/parser (帮助我们分析源代码)
npm install @babel/traverse (帮助我们快速找到 import 节点)
npm install @babel/core (babel 核心模块)
npm install --save-dev @babel/preset-env
#
Create-React-App 和 Vue-Cli 3.0 脚手架工具配置分析#
通过 CreateReactApp 深入学习 Webpack 配置#
Vue CLI 3 的配置方法及课程总结Vue CLI 官方配置参考 https://cli.vuejs.org/zh/config/#%E5%85%A8%E5%B1%80-cli-%E9%85%8D%E7%BD%AE