likes
comments
collection
share

前端进阶之Webpack(二)

作者站长头像
站长
· 阅读数 14

前言

不难看出这是一篇续章。

第一篇的内容以知识梳理为主,包括: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.jsbabelrc也是一样的,用于把Webpack.config.jsmodule.rules里的babel配置抽离出来,方便后期维护。

两者的作用确实和我之前的理解差不多,但作用范围却不同:

babel.config.js的作用范围是整个项目的代码,包括node_modules里的模块。

babelrc的作用范围是src目录下的代码,不包括node_modules里的模块。

使用babelrc的时候,要注意一个问题:

如果在src下的代码里直接引用了node_modules里的模块,比如time,而模块里又有新语法,babelrc因为作用范围,没有将新语法转换成老语法,导致浏览器无法理解,提示语法错误。

好用的Plugin

DLLPlugin

在介绍DLLPlugin前,我想先说说动态链接库的思想:

  1. 将网页依赖的基础模块抽离出来,打包到一个个单独的动态链接库中。在一个动态链接库中可以包含多个模块。
  2. 当需要导入的模块存在于某个动态链接库中时,这个模块不能被再次打包,而是去动态链接库中获取。
  3. 页面依赖的所有动态链接库都需要被加载。

最近比较火的pnpm也是引入了动态链接库的设计思想,解决了npmyarn的依赖包冗余问题,即依赖包的依赖包不好管理问题。

比如:

  1. 一个依赖包同时是多个依赖包的依赖,会被多次安装。
  2. a依赖包是b依赖包的依赖,跟着b依赖包一起被安装,没有单独配置在package.json的安装目录里,在项目里使用时,如果b依赖包被替换或者删除,使用a依赖包的地方就会出错。

pnpm加载所有用到的依赖包,集中管理,称为动态链接库,然后再构建一个依赖间的软连接,a依赖包无论是在其他依赖包里被引用,还是在项目里被引用,用的都是动态链接库里的那一个a依赖包。

话题回到DLLPlugin,主要作用就是将项目中的一部分代码添入动态链接库:

  1. 被添入动态链接库的代码可以保证在项目里只有一份,被所有使用到的组件共用。
  2. 动态链接库里的代码是打包过的,项目打包时,不需要再打包那部分代码,直接引入即可。
  3. 这是一个缺点,动态链接库里的代码不会热更新,修改后,要重新打包动态链接库,再启动项目。

一般的项目中,第二个优点比较明显,因为Webpakc打包的时候本来就会避免一个组件被多次打包。

在微应用项目中,每个应用都是一个项目,正常打包每个项目都会有自己的storeeventBus,微应用将他们拼成了一个整体,但彼此的状态和消息却不互通。

因此,第一个优点尤为重要,它使得例如storeeventBus这样的全局状态和全局消息能够跨项目传递。

只负责推荐,不负责配置。(其实是项目代码不方便直接贴出来,又懒得写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'), // 打包后的位置
        })
    ]
}