Webpack 介绍
编码规范
1. CommonJS 规范(nodejs)
一个文件就是一个模块
每个模块都有单独的作用域
通过 module.exports 导出成员
通过 require 函数载入模块
2.AMD(Asynchronous Module Definition)(浏览器)
3.目前浏览器规范(ES Module)
自动采用严格模式,忽略‘use strict‘
每个 ESM 模块都是单独的私有作用域
ESM 是通过 CORS 去请求外部 js 模块的
ESM 的 script 标签会延迟执行脚本
4.注意事项
ES Module 中可以导入 CommonJs 模块
CommonJs 中不能导入 ES Module 模块
ComonJs 始终只会导出一个默认成员
注意 import 不是结构导出对象
webPack 运行
1. 打包
webPack4.0 版本后 支持 0 配置 会按照约定 ‘src/index.js’ -> 'dist/main.js'
- 打包模式
yarn webpack --mode development
yarn webpack --mode none 运行最原始状态的打包
yarn webpack --mode production
只能打包 js 文件 打包 css 其它文件要配置对应 Loader (例 yarn add css-loader) 需安装。
- 在打包 css 后生成 js 文件,并没有去引用 css 所以要添加一个 style-loader 通过 style 标签的形式追加到页面上。
2. Loader
Loader 机制是实现前端模块化(webPack)的核心特性,借用不同的 Loader 就可以加载任何类型的资源, 工作原理原理负责资源文件从输入到输出的转换。
Loader 大致为 3 类:
编译转换类 例如:css-loader 转换为 js 形式中的 css 模块(文件编译)。
文件操作类 例如:file-loader 通常拷贝到输出的目录同时文件的访问路径向外导出。
代码检查类 例如:eslint-loader。
3. Babel
webpack 因为打包处理 import 和 export 而不会处理 es6,这时候需要 Babel,Babel 是一个工具集,主要用于将 ES6+ 代码转换为向后兼容的 JavaScript 语法,以便能够运行在当前和旧版本的浏览器或其他环境中。
webpack 只是一个打包工具 不会去处理代码中 es6 或者更高的新特性。
如何需要处理 可以通过给 js 代码配置加载器(Babel)实现特性(js 语法)的转换。
Babel 编译原理 4 步:
词法分析 实现方法 1.正则 2.有限状态机 在给定有限的情况下,将状态移到最终状态。
语法分析 例: es6->@bable/core ->AST ->new AST(多端使用) ->es5。
代码转换 AST-> new AST 多端。
代码生成 ast-> 生成 host 语言。
4. Plugin
相比于 loader,Plugin 拥有更宽的能力范围,Plugin 机制 就是开发中的钩子机制 类似于 web 事件 webPack 在不同的节点上挂载不同的插件去处理,钩子必须是一个函数或者包含 apply 的方法的对象,插件是通过让 webPack 生命周期的钩子(webPack 官网有详细钩子说明)中挂载任务函数实现扩展。
clean-webpack-plugin 去除打包后 dist 无关系的文件。
html-webpack-plugin 生成 index.html 可指定 html 模板生成 也可同时生成多个。
copy-webpack-plugin 拷贝静态文件。
5. 增强 webPack 工作体验
watch 工作模式 监听文件变化,自动运行打包 yarn build --watch 但是打开的网页不会自动刷新 5.2 BrowserSync 工具实现监听打包后文件自动刷新的功能 npm install browser-sync -g 安装后终端运行 browser-sync dist --files "*/"
操作效率降低 要使用两个工具 webpack 不断的把文件写入磁盘 browser-sync 不断的读取出来
Webpack Dev Server 是 webpack 官方推出的一个开发工具 提供了一个开发服务器 HTTP Server 并且 将 自 动编译和自动刷新浏览器等功能集成在一起 yarn add webpack-dev-serve --dev 安装过后在.bin 文件 夹下 提供了一个 webpack-dev-server 程序 此时可以运行 yarn webpack-dev-server 命令 也可以配置到 package.json 里面的 scripts 下 (为了提高工作效率 并没把结果写入到磁盘当中占时存放在内存当中 内 部的 HTTP Server 也就是从内存中提取出来发送给浏览器)命令 yarn webpack-dev-server 可以传入--open 可以自动唤起浏览器
6. source-map
映射源代码和打包后的代码之间的关系,方便调试
7. HMR 热更新
HMR 已经集中在了 webpack-dev-server 中 运行时 加--host 开启(可以在 webpack.config 文件里 devServe 中配置 hot:true 开启) 注意: 如果处理 HMR 的代码报错会导致自动刷新 刷新后页面的错误信息就会自动清除了 不容易发现,这种情况把 hot:true 修改为 hotOnly:true 去解决
大部分框架中都有成熟的 HMR 方案 使用就可以了
生成环境时可以把 webpack.HotModuleReplacementPlugin() 以及 devServer 中的 hotOnly / hot 注释掉,以免生成过于代码
8. 生产环境的优化
生产环境注重运行效率
开发环境注重开发效率
推出模式(mode) 为不同的工作环境创建不同的配置
配置文件根据环境不同导出不同配置 yarn build --env production 手动传递到 env 参数里
一个环境对应一个配置文件 webpack.common.js(公共配置) webpack.dev.js(开发环境) webpack.prod.js(生产环境配置) 开发环境和生产环境可以用 webpack-merge 模块合并(额外的)配置 这个时候打包就要 yarn webpack --config webpack.dev/prodction.js 指定模式打包(可以直接定义到 package.json 中 scripts 中方便使用)
webpack 生产工作工作中有 Tree Shaking (并不是某一个配置选项,一组功能搭配使用的效果,会在 production 模式下自动启动。 自动去掉未引用的代码) 功能
Tree Shaking 前提是 ES Modules, 由 webpack 处理的代码必须是 ESM 但是如果@babel/preset-env 插件工作时 是 commonJs 组织的代码就不会生效 Tree Shaking 但是再最新的 babel-loader 中自动关闭了 ESM(代码转换为 commonJs 代码)转换的插件
webpack 里配置 optimization 对象下配置 usedExports:true 只导出使用的成员 默认是 true 的 production 环境下不配置就是 true (minimize: true)代码压缩功能 与以上同理
concatenateModules: true, //尽可能的将所有模块合并输出到一个函数中 提升了运行效率 也减少的代码体积 特性也被称为 Scope Hoisting 作用域提升
sideEffects: true, //检查模块是否有副作用开启此功能 package.json 中也要配置"sideEffects":false(这里设置代码没有副作用) 检查没用到的模块就不会在打包 比如 import {buttom} from "ui" 其余的模块就不会打包进去 只会打包 buttom
代码分割 Code Splitting
多入口打包 试用于多页面程序 一个页面对应一个打包入口,公共部分提取到一个单独的文件中
按需加载 动态导入的模块会被自动分包 在代码片段中 使用 import ('***').then((model)=>{操作}) vue 路由就是如此处理
将 css 代码 重打包中提取的插件 mini-css-extract-plugin 可以实现 css 模块的按需加载(css 的 loader 还需要配置一下,配置后以 link 引入),optimize-css-assets-webpack-plugin 插件(如果配置到 optimization 下的 minimize:[] 数组中 此时就由是否开启压缩功能去控制 自定义压缩插件了) //以压缩文件的形式输出 css
输出文件名 Hash 解决静态缓存 一般 filename 中添加 由 3 种 1. filename: "[name]-[hash].css", 【hash】z 占位符使用 2.filename: "[name]-[chunkhash].css", 【chunkhash】同路 hash 3.filename: "[name]-[contenthash].css", //不同文件就有不同 hash 可以通过【hash:8】指定 hash 长度为 8