# 现代模式打包

# 介绍

打包应用的过程中通常会使用babel对代码进行转译,使得一些js的新特性也能在低版本浏览器中正常运行,但是如果一些用户使用的浏览器版本很高,足以支持这些特性,那么下载的js文件如果也被转译了就会带来浪费,而现代模式打包应用就是解决这个问题的,对支持新特性的用户分发es6代码,对不支持分发转移后的代码。

# 原理

<script type="module" src="..."></script>

当script标签碰到type="module"时,就会将对应文件作为一个module运行,如果浏览器不支持type="module"就会忽略这个脚本的执行,此时就需要用到nomodule来进行降级处理:

<script nomodule src="..."></script>

在浏览器不识别type="module"的时候,执行nomodule中的代码。

# 使用

Vue CLI中直接提供了现代模式构建的方法:

vue-cli-service build --modern

从打包过程和打包结果可以看出,其实就是执行了两次webpack打包过程,以此用了babel进行转移,称为legacy build,一次没有进行转移,称为modern build。

# 实现方法

每一次打包,都会将打包的资源通过htmlWebpackPlugin内联进html模板中,两次打包后就会有两者的资源,legacy build时内联的标签会有nomodule=""的属性,在modern build时,就会将该属性替换成nomodule,然后modern build的标签会添加type="module"属性。其还针对Safari 10.1不识别nomodule导致执行两套资源的bug进行了fix。详细可见:node_modules/@vue/cli-service/lib/webpack/ModernModePlugin.js

# 最后

**注意:现代模式分发的代码受跨域限制,例如你的html中引用了第三方资源,并且script有type="module"的属性,第三方服务器头部需要设置Access-Controll-Allow-Origin: ***