前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >『手撕Vue-CLI』编译模板『上』

『手撕Vue-CLI』编译模板『上』

原创
作者头像
BNTang
修改2024-05-27 07:46:14
71
修改2024-05-27 07:46:14
举报

前言

经『手撕Vue-CLI』完善提示信息后,nue-cli 的 create 指令已经实现了基本的功能,但是除了基本功能外,还有一些功能需要完善,比如模板的编译。

编译模板

为什么要起这么一篇文章来单独拆解编译模板这个功能呢?接下来的内容一起带着这个疑问来看。

为什么要编译模板

编译模板编译模板,利用模板就代表着有些内容咱们是不确定的,需要在运行时才能确定的,比如利用 create 指令创建项目时,项目名称、项目描述、作者等信息都是不确定的,需要在运行时才能确定的。

这些信息需要用户提供才能知晓,所以需要提前准备好模板,然后在运行时根据用户提供的信息来替换模板中的变量。

在之前的文章里,已经对 vue-simple-template 模板进行了完善。尚待完善的是 vue-advanced-template,这是一个需要编译后才能使用的模板。

下载 vue-advanced-template

居然要完成这个模板的编译,先下载下来,利用自己编写的 nue-cli create 进行下载:

代码语言:shell
复制
nue-cli create example

在我下载过程中,发现 GitHub 对应的这个模板我没有发布版本号,我就去发布了一个 v1.0.0,如果有直接观看这篇文章不懂这个如何创建的,可以去看看我之前所发布的文章即可。

发布好了之后,在终端执行上面我给出的命令,进行拉取下载需要编译的模板项目如下:

这样咱们需要的项目就已经有了,这个时候就可以先将部分代码给注释掉了,因为我不想每次测试都反复去拉取,我直接将地址写死在代码里,这样就不用每次都去拉取了。

注释掉的代码如下:

在定义一个 sourcePath 变量,将模板的路径写死在这里:

代码语言:javascript
复制
const sourcePath = `C:\\Users\\BNTang\\.nue-template\\vue-advanced-template`;

上面的地址你自己根据实际情况来更改为你自己的地址即可,这样就不用每次都去拉取了。

编译模板

模板下载下来了,先打卡模板目录中的 ask.js 文件,这个文件是用来获取用户输入的信息的,这个文件的内容如下:

代码语言:javascript
复制
module.exports = [
    {
        type: 'input',
        name: 'name',
        message: 'project-name?',
    },
    {
        type: 'confirm',
        name: 'private',
        message: 'ths resgistery is private?',
    },
    {
        type: 'input',
        name: 'author',
        message: 'author?',
    },
    {
        type: 'input',
        name: 'description',
        message: 'description?',
    }
]

暴露出去了一个数组,数组中包含了一些对象,每个对象都是一个问题,这个问题是用来获取用户输入的信息的。

看了这个文件,再看看 package.json 文件,在这个文件中有几个信息我是利用 <%=name%> 表示一个变量,它会在渲染时被替换为具体的值。

经过我如上这么一番介绍之后你要知识,需要编译的模板已经下载来了,模板目录中有两个比较核心的文件,分别是 ask.jspackage.json

ask.js 文件是用来获取用户输入的信息的,package.json 文件是用来渲染的,这两个文件是比较核心的文件,也是完成编译的关键。

接下来就是改造代码时刻,在之前的代码中,我们是直接将模板进行拷贝到指定路径中,现在我们需要将模板进行编译,将用户输入的信息替换到模板中。

所以需要根据当前模板下是否有 ask.js 文件来判断是否需要编译,如果有这个文件,就需要编译,如果没有这个文件,就不需要编译。

这里得要利用到 fs 模块,通过 fs 模块来判断是否有这个文件,如果有这个文件,就需要编译,如果没有这个文件,就不需要编译。

先导入 fs 模块:

代码语言:javascript
复制
const fs = require('fs');

然后在 create 方法中,根据是否有 ask.js 文件来判断是否需要编译:

代码语言:javascript
复制
const askPath = path.join(sourcePath, 'ask.js');
if (!fs.existsSync(askPath)) {
    await waitLoading('copying template...', ncp)(sourcePath, destPath);
} else {
}

这样就可以根据是否有 ask.js 文件来判断是否需要编译了,接下来就是编译的逻辑了。

编译逻辑

编译逻辑就是将用户输入的信息替换到模板中,这里需要用到 Metalsmith 这个库,这个库的作用就是将用户输入的信息替换到模板中,它就有这个能力。

官网我就不贴出来大家自行去 npm 官网搜索即可,这里直接安装 Metalsmith:

代码语言:shell
复制
npm install metalsmith --save

安装好了之后,导入 Metalsmith:

代码语言:javascript
复制
const Metalsmith = require('metalsmith');

然后在 else 代码块中,编写编译逻辑:

代码语言:javascript
复制
// 处理用户输入
await new Promise((resolve, reject) => {
    // 处理用户输入
    Metalsmith(__dirname)
        // 配置源目录
        .source(sourcePath)
        // 配置目标目录
        .destination(destPath)
        // 注册一个插件
        .use(async (files, metal, done) => {
            done();
        })
        .use(async (files, metal, done) => {
            done();
        })
        .build((err) => {
            if (err) {
                reject(err);
            } else {
                resolve();
            }
        });
});
  • Metalsmith(__dirname) 这个方法是用来创建一个 Metalsmith 实例的,这个实例中包含了一些方法,比如 source、destination、use、build 等方法。
  • .source(sourcePath) 这个方法是用来配置源目录的,这里就是我们的模板目录。
  • .destination(destPath) 这个方法是用来配置目标目录的,这里就是我们的项目目录。

为什么我这里写了两个 .use 方法呢?因为 Metalsmith 是一个流式处理的库,它是通过 .use 方法来注册插件的,这里我注册了两个插件,第一个插件是用来处理用户输入的,第二个插件是用来处理模板的。

本章先到这里编译内容有点多我在分一个文章来写。

我正在参与2024腾讯技术创作特训营最新征文,快来和我瓜分大奖!

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 编译模板
    • 为什么要编译模板
    • 下载 vue-advanced-template
    • 编译模板
    • 编译逻辑
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档