「这是我参与11月更文挑战的第21天,活动详情查看:2021最后一次更文挑战」
先来做下准备工作:
-
删除
webpack_babel目录下的build、dist和node_modules文件夹; -
拷贝一份
webpack_babel目录,并重命名为webpack_vue; -
打开
VS Code的终端,切换目录到webpack_vue下,运行npm install安装当前项目(webpack_vue)所需依赖,安装完成后,项目目录如下:
前面我们已经讲了 Webpack 可以对 js、css、font 和 img 等资源进行打包,而下面要讲的我们自己编写的 Vue 的代码事实上也是 JavaScript 代码,所以我们可以看下 Webpack 对我们编写的 Vue 的代码的打包。
我们打开 ./src/main.js 文件,将其中的内容修改如下:
import { sum } from './js/math.js';
import { createApp } from 'vue'; // 以模块的方式引入 Vue 中的 createApp 函数
const { formatPrice } = require('./js/format.js');
import './js/element';
console.log(sum(10, 20));
console.log(formatPrice(100));
这次我们使用 Vue 的方式和之前不同了,之前我们使用 Vue 时,要么是通过 CDN 引入:
<script src="https://unpkg.com/vue@next"></script>
要么是通过下载到本地的 Vue 源码文件进行引入:
<script src="../js/vue.js"></script>
这次我们是这样引入 Vue 的:
import { createApp } from 'vue';
这种在 js 代码中引入 Vue 的方式,意思是把 vue 当做一个模块,然后从这个模块中导入 createApp 这个函数,以便后续使用。而既然要将 vue 当成一个模块来使用,就必须在当前项目中有这个模块(即当前项目依赖 vue),也就意味着在当前项目的 node_modules 目录下要有这个模块,因此,以这种方式使用 Vue 就需要我们先来安装这个 vue 模块:
npm install vue@next
注意:
- 当前(
2021-11-21)Vue官方还没有把Vue的版本默认切换到3.x,所以我们安装Vue3.x还需要在vue后面带上@next。否则,直接npm install vue安装的还是Vue2.x。- 这里的命令不需要也不应该添加
-D(虽然加上也不会报错,但建议按照规范来),因为Vue除了开发阶段,在生产阶段(我们把打包出来的包部署到静态服务器上后,用户访问时会将其下载下来,而下载下来的代码中也应该包含Vue的核心代码)也是需要使用的。
安装完成后,我们从 vue 模块中导入 createApp 函数就没有问题了。下面,我们就可以像之前一样使用这个 createApp 函数创建 Vue 的应用了:
import { sum } from './js/math.js';
import { createApp } from 'vue';
const { formatPrice } = require('./js/format.js');
import './js/element';
console.log(sum(10, 20));
console.log(formatPrice(100));
// 编写 Vue 相关的代码
const app = createApp({
template: '<h2>我是 Vue 渲染出来的</h2>',
data() {
return {
title: '你好'
}
}
});
app.mount('#app');
上面代码中,我们将创建出来的 Vue 应用挂载到了 id 为 app 的 HTML 元素上,这个元素其实在当前项目下 public 文件夹下的 index.html 这个模板文件中已经有了:
那么现在如果我们对项目进行打包,然后在浏览器上运行的话,刚才编写的这段 Vue 的代码应该是能渲染出对应的内容(template 选项中的内容)的,因为 Vue 的代码本质上也是 JavaScript 代码,而 Webpack 默认是可以对 JavaScript 代码进行打包的,所以 Webpack 应该是能对我们刚才编写的这段 Vue 的代码进行打包的。那我们来运行 npm run build 命令打包看下效果(打包过程可能会慢一点点,因为 Vue 的源代码稍微有点多):
可以看到,打包过程没有问题,再来用 Live Server 插件在浏览器中打开 ./build/index.html 文件看下页面效果:
你会发现,页面上并没有显示 template 选项中的内容,那为什么没有显示对应的内容呢?打包的过程没问题,但把打包后的代码运行在浏览器上时,对应的内容却没有显示,那我们打开浏览器的控制台看下有没有给我们相关的信息:
你会发现,控制台打印了两条警告信息,上面那条我们暂时可以忽略,我们来看下面那条警告(这条警告可能称之为错误会更好)。这条警告中提到:Component provided template option but runtime compilation is not supported in this build of Vue.,意思是:组件提供了 template 选项,但在当前这个 Vue 构建版本中是不支持运行时编译的。
这里说的“组件”指的就是我们给 createApp 函数传入的第一个参数对象,它是一个根组件。在这个根组件里我们确实写了 template 选项,那这个 template 到时候一定是会被 Vue 的源代码解析的,但事实上,Vue 的源代码有很多版本,这些版本又可以分为两大类:
Runtime + Compiler:即“运行时 + 编译器”版本,如果需要在客户端上编译模板(例如,将一个字符串传递给template选项,或者使用元素的DOM内HTML作为模板挂载到某个元素上),这时就需要编译器,因此就需要这个完整的构建版本,即Runtime + Compiler版本;Runtime-only:即”仅运行时“版本,如果不需要在客户端上编译模板,用这个版本即可。
也就是说,如果在代码中没有使用 template 选项(你可能会问,没有 template 选项,那到时候还怎么渲染相应的内容呢?其实我们还有其它方式渲染内容,比如说使用 render 函数或者写成 .vue 文件,.vue 文件的解析会有相应的办法,具体后面会讲),就可以不要编译器,使用仅运行时版本即可。
但是,如果我们写了 template 选项,那就必须使用 Runtime + Compiler 版本了,因为这个版本中包含了 Compiler 的功能,而 Compiler 最主要的功能就是用来对 template 进行编译的。
而 Vue 模块默认使用的是 Runtime-only 版本的构建版本(vue.runtime.esm-bundler.js),这就意味着它不包含对 template 这部分代码的编译功能。也就是说我们现在用的是默认的仅运行时版本,因此我们在编写的组件中使用的 template 最终相当于没有编译成功,所以在浏览器页面中就没有对应的效果。
正因如此,控制台中才出现了 Vue 提供给我们的那个警告信息,当然,它这里建议我们去给 vue 起别名(alias),这个我们后面再讲。现在,我们需要明确的是,当前我们引用的 Vue 的版本是默认的“仅运行时”版本,不满足我们的需求,我们需要引入 Vue 的“运行时 + 编译器”版本。