✊不积跬步,无以至千里;不积小流,无以成江海
常见 loader 和 plugin 的区别是什么
常见 loader
-
babel-loader 把 JS/TS 变成 JS
-
ts-loader 把 TS 变成 JS,并提示类型错误
-
markdown-loader 把 markdown 变成 html
-
html-loader 把 html 变成 JS 字符串
-
sass-loader 把 SASS/SCSS 变成 CSS
-
css-loader 把 CSS 变成 JS 字符串
-
style-loader 把 JS 字符串变成 style 标签
-
postcss-loader 把 CSS 变成更优化的 CSS;5678如果一起用,最好的顺序是5867
-
vue-loader 把单文件组件(SFC)变成 JS 模块
-
thread-loader 用于多进程打包
常见 plugin
-
html-webpack-plugin 用于创建 HTML 页面并自动引入 JS 和 CSS
-
clean-webpack-plugin 用于清理之前打包的残余文件
-
mini-css-extract-plugin 用于将 JS 中的 CSS 抽离成单独的 CSS 文件
-
SplitChunksPlugin 用于代码分包(Code Split)
-
DllPlugin + DllReferencePlugin 用于避免大依赖被频繁重新打包,大幅降低打包时间
-
eslint-webpack-plugin 用于检查代码中的错误
-
DefinePlugin 用于在 webpack config 里添加全局变量
-
copy-webpack-plugin 用于拷贝静态文件到 dist
二者的区别
- loader 是文件加载器
◦ 功能:能够对文件进行编译、优化、混淆(压缩)等,比如 babel-loader / vue-loader
◦ 运行时机:在创建最终产物之前运行
- plugin 是 webpack 插件
◦ 功能:能实现更多功能,比如定义全局变量、Code Split、加速编译等
◦ 运行时机:在整个打包过程(以及前后)都能运行
webpack 如何解决开发时的跨域问题?
在开发时,我们的页面在localhost:8080,JS 直接访问后端接口(如https://yiqilaiwan.com 或 http://localhost:3000 )会报跨域错误。
为了解决这个问题,可以在 webpack.config.js 中添加如下配置:
module.exports = {
//...
devServer: {
proxy: {
'/api': {
target: 'http://yiqilaiwan.com',
changeOrigin: true,
},
},},
};
此时,在 JS 中请求 /api/users 就会自动被代理到 https://yiqilaiwan.com/api/users 。
如果要访问的是 HTTPS API,那么就需要配置 HTTPS 证书,否则会报错。不过,如果在 target 下面添加 secure: false ,就可以不配置证书且忽略 HTTPS 报错。
如何实现 tree-shaking?
是什么
tree-shaking 就是让没有用到的 JS 代码不打包,以减小包的体积。
怎么做
背下文档说的这几点:
-
怎么删
a. 使用 ES Modules 语法(即 ES6 的 import 和 export 关键字)
b. CommonJS 语法无法 tree-shaking(即 require 和 exports 语法)
c. 引入的时候只引用需要的模块
- 要写 import {cloneDeep} from 'lodash-es' 因为方便 tree-shaking
- 不要写 import from 'lodash' 因为会导致无法 tree-shaking 无用模块
-
怎么不删:在 package.json 中配置 sideEffects,防止某些文件被删掉
a. 比如我 import 了 x.js,而 x.js 只是添加了 window.x 属性,那么 x.js 就要放到sideEffects 里
b. 比如所有被 import 的 CSS 都要放在 sideEffects 里
-
怎么开启:在 webpack config 中将 mode 设置为 production(开发环境没必要tree-shaking)
a. mode: production 给 webpack 加了非常多。
如何提高 webpack 构建速度?
-
使用 DllPlugin 将不常变化的代码提前打包编程一个动态链接库,并复用,如 vue、react
-
使用 thread-loader 或 HappyPack(过时)进行多线程打包,即同时放在4/8..个cpu上同时打包
-
处于开发环境时,在 webpack config 中将 cache 设为 true,也可用 cache-
loader(过时)
- 处于生产环境时,关闭不必要的环节,比如可以关闭 source map
webpack 与 vite 的区别是什么?
开发环境区别
-
vite 自己实现 server,不对代码打包,充分利用浏览器对
<script type=module>的支持i. 假设 main.js 引入了 vue
ii. 该 server 会把 import { createApp } from 'vue' 改为
import {createApp } from "/node_modules/.vite/vue.js"这样浏览器就知道去哪里找 vue.js 了 -
webpack-dev-server 常使用 babel-loader 基于内存打包,比 vite 慢很多很多很多
i. 该 server 会把 vue.js 的代码(递归地)打包进 main.js
生产环境区别
-
vite 使用 rollup + esbuild 来打包 JS 代码
-
webpack 使用 babel 来打包 JS 代码,比 esbuild 慢很多很多很多
i. webpack 能使用 esbuild 吗?可以,你要自己配置(很麻烦)。
-
文件处理时机
i. vite 只会在你请求某个文件的时候处理该文件
ii. webpack 会提前打包好 main.js,等你请求的时候直接输出打包好的 JS 给你
目前已知 vite 的缺点有:
-
热更新常常失败,原因不清楚
-
有些功能 rollup 不支持,需要自己写 rollup 插件
-
不支持非现代浏览器
webpack 怎么配置多页应用?
- 先定义路径
- 然后用html-webpack-plugin指定名字
- 用chunks指定js路径,通过chunks name和js进行了关联
- 这样配置会有一个「重复打包」的问题:假设 app.js 和 admin.js 都引入了vue.js,那么 vue.js 的代码既会打包进 app.js,也会打包进 admin.js。
- 需要使用
optimization.splitChunks将共同依赖单独打包成 common.js(HtmlWebpackPlugin会自动引入 common.js)
万一思考无限多页面的情况。
- 获取指定路径下的所有文件
- filter只以js结尾的文件
- 对每个js结尾文件的js去掉
- 然后对应上面的生成多个entry对象 & plugins数组
- 最后把生成的路径扩展过来
swc、esbuild 是什么?
swc
实现语言:Rust
功能:编译 JS/TS、打包 JS/TS
优势:比 babel 快很多很多很多(20倍以上)
能否集成进 webpack:能
使用者:Next.js、Parcel、Deno、Vercel、ByteDance、Tencent、Shopify……
做不到:
-
对 TS 代码进行类型检查(用 tsc 可以)
-
打包 CSS、SVG
esbuild
实现语言:Go
功能:同上
优势:比 babel 快很多很多很多很多很多很多(10~100倍)
能否集成进 webpack:能
使用者:vite、vuepress、snowpack、umijs、blitz.js 等
做不到:
-
对 TS 代码进行类型检查
-
打包 CSS、SVG