阅读 930

Vue 项目之 Webpack 打包 Vue 代码(1)

「这是我参与11月更文挑战的第21天,活动详情查看:2021最后一次更文挑战

先来做下准备工作:

  1. 删除 webpack_babel 目录下的 builddistnode_modules 文件夹;

  2. 拷贝一份 webpack_babel 目录,并重命名为 webpack_vue

  3. 打开 VS Code 的终端,切换目录到 webpack_vue 下,运行 npm install 安装当前项目(webpack_vue)所需依赖,安装完成后,项目目录如下:

    image-20211121114631816

前面我们已经讲了 Webpack 可以对 jscssfontimg 等资源进行打包,而下面要讲的我们自己编写的 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
复制代码

注意:

  1. 当前(2021-11-21Vue 官方还没有把 Vue 的版本默认切换到 3.x,所以我们安装 Vue3.x 还需要在 vue 后面带上 @next。否则,直接 npm install vue 安装的还是 Vue2.x
  2. 这里的命令不需要也不应该添加 -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 应用挂载到了 idappHTML 元素上,这个元素其实在当前项目下 public 文件夹下的 index.html 这个模板文件中已经有了:

image-20211121144042076

那么现在如果我们对项目进行打包,然后在浏览器上运行的话,刚才编写的这段 Vue 的代码应该是能渲染出对应的内容(template 选项中的内容)的,因为 Vue 的代码本质上也是 JavaScript 代码,而 Webpack 默认是可以对 JavaScript 代码进行打包的,所以 Webpack 应该是能对我们刚才编写的这段 Vue 的代码进行打包的。那我们来运行 npm run build 命令打包看下效果(打包过程可能会慢一点点,因为 Vue 的源代码稍微有点多):

image-20211121145528440

可以看到,打包过程没有问题,再来用 Live Server 插件在浏览器中打开 ./build/index.html 文件看下页面效果:

image-20211121180528374.png

你会发现,页面上并没有显示 template 选项中的内容,那为什么没有显示对应的内容呢?打包的过程没问题,但把打包后的代码运行在浏览器上时,对应的内容却没有显示,那我们打开浏览器的控制台看下有没有给我们相关的信息:

image-20211121150532650

你会发现,控制台打印了两条警告信息,上面那条我们暂时可以忽略,我们来看下面那条警告(这条警告可能称之为错误会更好)。这条警告中提到: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 选项,或者使用元素的 DOMHTML 作为模板挂载到某个元素上),这时就需要编译器,因此就需要这个完整的构建版本,即 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 的“运行时 + 编译器”版本。

文章分类
前端
文章标签