前端进阶之Webpack(二)
前言
不难看出这是一篇续章。
第一篇的内容以知识梳理为主,包括:node
基础,Webpack
原理和配置详解。
这篇的内容以实践总结为主,主要有两部分:知识误区和好用的Plugin
。
知识误区
babel和polyfill
我在很长一段时间都以为babel
能把polyfill
的活一起做了,可以把所有es6
以上的语法和API
都转换成es5
语法和API
。
直到在处理IE
兼容性问题时,控制台一直报错:不支持Promise
,引起了我的思考。因为按我当时的理解,Promise
应该被babel
转换了。
经过一番查阅资料才发现二者的区别:
babel
用于将新语法转换成老语法,例如将箭头函数转换成普通函数。
polyfill
用于实现浏览器不支持的新API
,例如Promise
。
由于Chrome
对新API
的支持度比较好,框架没有引入polyfill
的问题一直到测试IE
兼容性时才被发现。打开一片的白屏,结果是细节上的知识误区导致的。
如何引用的话,网上详细的引入方法很多,我这里就不搬了,提一个当时踩的小坑:3.0以下版本的core-js
要和polyfill
一起使用,core-js
@3.x包含了polyfill
的功能,不再需要polyfill
,和polyfill
一起使用会出错。
babel.config.js和babelrc
我在很长一段时间以为babel.config.js
和babelrc
也是一样的,用于把Webpack.config.js
中module.rules
里的babel
配置抽离出来,方便后期维护。
两者的作用确实和我之前的理解差不多,但作用范围却不同:
babel.config.js
的作用范围是整个项目的代码,包括node_modules
里的模块。
babelrc
的作用范围是src
目录下的代码,不包括node_modules
里的模块。
使用babelrc
的时候,要注意一个问题:
如果在src
下的代码里直接引用了node_modules
里的模块,比如time
,而模块里又有新语法,babelrc
因为作用范围,没有将新语法转换成老语法,导致浏览器无法理解,提示语法错误。
好用的Plugin
DLLPlugin
在介绍DLLPlugin
前,我想先说说动态链接库的思想:
- 将网页依赖的基础模块抽离出来,打包到一个个单独的动态链接库中。在一个动态链接库中可以包含多个模块。
- 当需要导入的模块存在于某个动态链接库中时,这个模块不能被再次打包,而是去动态链接库中获取。
- 页面依赖的所有动态链接库都需要被加载。
最近比较火的pnpm
也是引入了动态链接库的设计思想,解决了npm
和yarn
的依赖包冗余问题,即依赖包的依赖包不好管理问题。
比如:
- 一个依赖包同时是多个依赖包的依赖,会被多次安装。
a
依赖包是b
依赖包的依赖,跟着b
依赖包一起被安装,没有单独配置在package.json
的安装目录里,在项目里使用时,如果b
依赖包被替换或者删除,使用a
依赖包的地方就会出错。
pnpm
加载所有用到的依赖包,集中管理,称为动态链接库,然后再构建一个依赖间的软连接,a
依赖包无论是在其他依赖包里被引用,还是在项目里被引用,用的都是动态链接库里的那一个a
依赖包。
话题回到DLLPlugin
,主要作用就是将项目中的一部分代码添入动态链接库:
- 被添入动态链接库的代码可以保证在项目里只有一份,被所有使用到的组件共用。
- 动态链接库里的代码是打包过的,项目打包时,不需要再打包那部分代码,直接引入即可。
- 这是一个缺点,动态链接库里的代码不会热更新,修改后,要重新打包动态链接库,再启动项目。
一般的项目中,第二个优点比较明显,因为Webpakc
打包的时候本来就会避免一个组件被多次打包。
在微应用项目中,每个应用都是一个项目,正常打包每个项目都会有自己的store
和eventBus
,微应用将他们拼成了一个整体,但彼此的状态和消息却不互通。
因此,第一个优点尤为重要,它使得例如store
和eventBus
这样的全局状态和全局消息能够跨项目传递。
只负责推荐,不负责配置。(其实是项目代码不方便直接贴出来,又懒得写demo
)
CopyWebpackPlugin
这是一个比较简单粗暴的插件,因为项目打包前的目录和打包后的目录往往是不一致的,所以项目访问静态资源的时候,打包后会出现地址访问错误的问题,通过CopyWebpackPlugin
可以把静态资源拷贝到指定的位置,从而避免错位问题。
由于我做的是海外的微应用项目,多个项目的多语言管理是一个关键问题,由于每个项目存放多语言文件的位置都不同,给vue-i18n
的封装造成了很大困扰,好在最后想到用CopyWebpackPlugin
将每个项目的多语言存放在了固定的{applicationName}/locale
目录下解决了问题。
CopyWebpackPlugin
的使用:
const CopyWebpackPlugin = require('copy-webpack-plugin');
module.exports = {
plugins: [
new CopyWebpackPlugin({
from: path.join(__dirname, 'src', 'static'), // 打包前的位置
to: path.join(__dirname, 'static'), // 打包后的位置
})
]
}
转载自:https://juejin.cn/post/7138401110359801892