ES模块是JavaScript在ES2015版本开始提供的语言标准级别的模块化方案,在此之前JavaScript一直没有语言级别的模块化体系。本文我们来看一下vue.js中的ES模块的使用。
Vue 2.6版本的一个新特性是包含了一个ES模块浏览器构建,允许您像这样在页面上加载Vue:
<script type="module"> import Vue from 'https://unpkg.com/vue@2.6.0/dist/vue.esm.browser.min.js'; new Vue({ ... }); </script>
这意味着您可以编写模块化的Vue应用程序,无需构建步骤即可在浏览器中运行(当然是在受支持的浏览器中)。
让我们探究一下这个特性背后的原因,并看看如何使用它。
关于JavaScript模块的一点背景知识
当JavaScript被创建时,大多数人并不清楚它最终会成为世界上最流行的编程语言。
它主要用于触发警报窗口和闪烁的文本,因此假定在一个脚本中编写所有代码就足够了。
但在Node.js和大型spa的时代,JavaScript应用程序可能有数百个依赖项和数千行代码。
要开发这样一个可扩展的应用程序,几乎需要将代码分成模块,并允许以可伸缩的方式导入依赖项,使代码具有可维护性和效率。
模块系统
最终,创建了JavaScript模块系统,最初只是为了Node.js。客户端模块的用例也很强大,但其中的困难是,如果它们有任何用处,每个浏览器都必须支持它们。
浏览器模块加载器试图解决这个问题,但是主流的解决方案是使用Webpack或Rollup之类的模块捆绑器将模块化的JavaScript编译回非模块化的表单。
虽然非常有用,但是模块系统和捆绑器已经成为web开发的另一个复杂领域。
模块最终在ES2015年添加到ECMA标准中,在2019年,现代浏览器原生支持ES模块,允许您编写模块化的JavaScript,无需编译即可直接在浏览器中运行。
这里有一个例子:
index.html (client-side)
<script type="module"> import {addTextToBody} from './utils.mjs'; addTextToBody('Modules are pretty cool.'); </script>
utils.mjs (server-side)
export function addTextToBody(text) { const div = document.createElement('div'); div.textContent = text; document.body.appendChild(div); }
Jake Archibald的ECMAScript模块在浏览器中的代码示例。
Vue.js构建
让我们改变一下策略,讨论一下Vue构建。
由于Vue.js库有许多不同的环境和用例,所以有许多可用的构建,包括UMD构建、CommonJS构建和ES模块构建。
例如,如果你想在浏览器中直接使用Vue,你可以使用UMD构建:
index.html
<script src="https://mycdn.com/vue.js"></script> <script> new Vue(); </script>
UMD构建在全局名称空间中声明Vue对象,使其对加载和解析Vue脚本之后声明的任何脚本都可用。
这是在项目中包含JS库的“经典”方法,但它也有很多缺点,例如脚本必须按使用顺序加载,两个冲突的版本可以被添加到同一个页面,等等。
但是它对于快速原型开发很方便,因为它不需要构建步骤。
模块视图
CommonJS和ES模块构建了一个基于不同模块标准的模块导出Vue。它们的用途是捆绑工具,如Webpack或Rollup。例如,用户会创建这样一个“输入文件”:
app.js
import Vue from "vue"; new Vue();
bundler将这个脚本和Vue模块编译成一个构建文件,例如/dist/bundle.js,客户端是这样使用的:
index.html
<script src="/dist/bundle.js"></script>
在浏览器中使用Vue作为模块
如果提供了ES模块构建,我们不能在浏览器中使用它吗?
如果您尝试在浏览器中使用Vue 2.5 ES模块构建,即
index.html
<script type="module" src="vue.esm.js"></script>
它不会工作。当然,它会加载,但你会遇到这样的控制台错误:
未捕获的ReferenceError:没有定义进程
这是因为es模块内置版本<=2.5.x只打算由bundler使用。
但是ES模块不是一个标准吗?为什么它在服务器上而不是在浏览器上工作?
是的,但是构建中包含了对Node.js全局变量(如process)的引用,因为这将有助于优化Vue的绑定版本,并且将在绑定过程中被删除。这直到现在才被认为是一个问题,因为没有人在浏览器中使用ES模块!
但从VUE 2.6开始,VUE包中现在有另一个版本可供使用,专门用于浏览器vue.esm.browser.js。
如何使用浏览器模块构建
这个新的ES模块构建的Vue可以加载到浏览器没有捆绑器。这里有一个例子:
index.html
<!DOCTYPE html> <html> <head> <title>Vue.js ESM</title> </head> <body> <div id="app"> {{ message }} </div> <script type="module" src="vue.mjs"></script> <script type="module" src="app.mjs"></script> </body> </html>
app.mjs
import Vue from './vue.mjs'; new Vue({ el: '#app', data: { message: 'Hello Vue 2.6.0-beta1 ESM Browser Build!' } });
要使此工作正常,您需要静态地为app.mjs和vue.mjs提供服务。后一个文件将被别名为vue es browser构建,即node_modules/vue/dist/vue.esm.browser.js。
虽然不需要使用.mjs扩展,但google开发者的这篇文章建议将javascript模块与经典的非模块脚本区分开来。
回退
如果要使用ES模块构建,可能需要提供一个后备方案,因为只有现代浏览器支持ES模块。
按照上面的示例,您可以设置一个非常简单的Webpack配置来并行地打包这段代码:
webpack.config.js
module.exports = { entry: './app.js', output: { path: path.resolve(__dirname, './dist'), publicPath: '/dist/', filename: 'build.js' }, module: { // add Babel here if needed }, resolve: { alias: { './vue.js': './node_modules/vue/dist/vue.esm.browser.js' } } };
现在可以使用nomodule属性在页面中加载捆绑包。支持模块的浏览器将知道不加载nomodule脚本,而不识别模块的浏览器将跳过前两个脚本,只加载回退。
index.html
<script type="module" src="vue.mjs"></script> <script type="module" src="app.js"></script> <script nomodule src="/dist/build.js"></script> <!--Fallback-->
使用Vue作为ES模块有什么好处?
浏览器模块加载和解析的效率目前低于经典的代码分割脚本。由于你可能仍然需要使用一个捆绑器来进行linting, TypeScript的转换,树的摇动等等,这也不会简化你的设置。
虽然我不是WordPress插件开发人员,但有人告诉我,浏览器模块构建在这里是很有用的,因为一个WordPress站点可能有多个插件,它们的Vue版本可能相互冲突。一个经典的脚本会污染全局命名空间,并可能导致问题,而模块不会。
但是如果您没有那个用例,为什么还要使用浏览器模块呢?
这里有几个(公认抽象的)原因:
-
JavaScript开发完全依赖于Webpack和Rollup是不好的,因为这是一个重要的瓶颈和失败的脆弱点。
-
保存一个本地的、标准化的解决方案将随着时间的推移简化web开发。我们可以摒弃所有竞争的模块系统,比如CommonJS。也许甚至Webpack和Rollup也会悄然消失,因为现在模块已经标准化了,一个标准化的捆绑解决方案正在被提出。
-
ES模块的浏览器实现是一个可以构建的平台。现在,将捆绑作为一个经典脚本更好,但这并不意味着它将永远如此。查看JS模块的下一步计划,了解谷歌计划的一些细节。
英文原文地址:https://vuejsdevelopers.com/2019/02/04/vue-es-module-browser-build/
以上就是Vue中的新功能:ES模块浏览器生成的详细内容,更多请关注html中文网其它相关文章!