这是我参与8月更文挑战的第3天,活动详情查看:8月更文挑战
最近在探索学习前端工程化的知识,发现了Vue mini小程序框架项目。从GitHub star数来看,了解Vue mini框架的人可能不多,它是一个可以用vue3 Composition API编写小程序的框架,与众多小程序开发框架(taro,wepy等)不同的是,它的底层直接依赖于 @vue/reactivity, 强调轻量的运行时,它既不依赖任何编译步骤,也不涉及任何 Virtual DOM。详见官方文档。不过目前要介绍的并不是该框架如何使用或者它的实现原理,而是由于该框架初始化的构建文件build.js代码量少,非常适合入门学习工程构建,接下来将分多篇文章输出相关知识。
首先,我们新建一个小程序项目,它的结构目录如下:
对于习惯了web开发的我们来说,先从最简单的一个痛点需求出发:原生wxss写样式太不方便了,我要用less编写样式代码,如何做?
项目准备
新建一个文件夹,比如就叫mini-demo,我们先将上面新建的初始化小程序的代码中所有的样式文件wxss后缀改为less,然后拷贝到mini-demo -> src的目录下,并在根目录下npm init创建一个package.json文件,后面会安装各种构建依赖包。
通常来说,使用less都会创建variables.less及mixins.less文件,目前我想将这两个less样式文件约定,统一放到src目录下叫做styles的文件夹中,然后在工程构建中将这两个文件内容逐一添加进各个样式文件中。
到此,项目准备工作已经完成,接下来我们要做的就是构建工程代码实现:
- 监听src目录下的less样式文件改动,实时将less文件编译成css,并将文件后缀名重新改为wxss
- 将src文件整体输出到dist目录
创建build.js
在根目录下创建build.js,并在package.json script中添加脚本
"dev": "node build.js",
复制代码
后续我们通过npm run dev方式启动运行构建代码
编写build.js构建脚本
首先,启动npm run dev后,我们要实现:
以上相关包的用法请自行查阅文档,下面直接上代码,配合注释不难阅读:
build.js
const chokidar = require('chokidar');
const fs = require('fs-extra');
const postcss = require('postcss');
const less = require('less');
const path = require('path'); // node 自带的,无需安装依赖包,直接引入即可
async function dev() {
// 对不同文件进行不同的处理,这里暂时只实现对样式文件的处理
const cb = (filePath) => {
if (/\.less$/.test(filePath)) {
processStyle(filePath);
return;
}
// 将文件拷贝到dist目录
fs.copy(filePath, filePath.replace('src', 'dist'));
}
chokidar
.watch(['src'], {
ignored: ['**/.{gitkeep,DS_Store}'],
})
.on('add', (filePath) => {
// 监听到有新的文件添加进来执行的逻辑
// styles 文件夹下的less样式文件不会打包进dist目录
if (filePath.includes(path.join('src', 'styles'))) return;
cb(filePath);
})
.on('change', (filePath) => {
// 文件内容改变触发的逻辑
console.log('change file: ' + filePath)
if (filePath.includes(path.join('src', 'styles'))) {
// 重新编译样式文件
recompileStyles();
return;
}
cb(filePath);
});
}
// 样式文件处理
async function processStyle(filePath,) {
let source = await fs.readFile(filePath, 'utf8');
// 在pages文件下的各个样式文件中注入variables和mixins定义的内容
source =
`@import '${path.resolve('src/styles/variables.less')}';\n` +
`@import '${path.resolve('src/styles/mixins.less')}';\n` +
source;
// 将less编译为css
const { css } = await less.render(source, {
filename: path.resolve(filePath),
});
// postcss可以利用各种插件对css内容进行处理,这里先暂时不用
const { css: wxss } = await postcss().process(css, { map: false, from: undefined });
// 修改less后缀为wxss并且将文件输出到dist目录
const destination = filePath.replace('src', 'dist').replace(/\.less$/, '.wxss');
await fs.copy(filePath, destination);
fs.writeFile(destination, wxss);
}
// 由于styles目录下的文件修改可能影响多个文件,所以重新遍历编译一遍所有页面样式文件
function recompileStyles() {
const watcher = chokidar.watch(['src/**/*.less', '!src/styles/**/*']);
watcher.on('add', (filePath) => {
processStyle(filePath);
});
watcher.on('ready', () => watcher.close());
}
dev()
复制代码
现在我们往styles目录的文件中增加测试数据
variables.less
@blue: blue;
复制代码
mixins.less
.backgroundBlue() {
background: @blue;
}
复制代码
打开src -> page -> index.less,我们往里面添加
.test {
.testone {
.backgroundBlue()
}
}
复制代码
最后运行npm run dev,可以看到dist目录成功生成:
点开index.wxss,可以看到less文件成功编译:
源码地址
仓库源码以序号对应每篇文章源码