小程序框架工程构建学习之使用less(01)

这是我参与8月更文挑战的第3天,活动详情查看:8月更文挑战

最近在探索学习前端工程化的知识,发现了Vue mini小程序框架项目。从GitHub star数来看,了解Vue mini框架的人可能不多,它是一个可以用vue3 Composition API编写小程序的框架,与众多小程序开发框架(taro,wepy等)不同的是,它的底层直接依赖于 @vue/reactivity, 强调轻量的运行时,它既不依赖任何编译步骤,也不涉及任何 Virtual DOM。详见官方文档。不过目前要介绍的并不是该框架如何使用或者它的实现原理,而是由于该框架初始化的构建文件build.js代码量少,非常适合入门学习工程构建,接下来将分多篇文章输出相关知识。

首先,我们新建一个小程序项目,它的结构目录如下:

image.png

对于习惯了web开发的我们来说,先从最简单的一个痛点需求出发:原生wxss写样式太不方便了,我要用less编写样式代码,如何做?

项目准备

新建一个文件夹,比如就叫mini-demo,我们先将上面新建的初始化小程序的代码中所有的样式文件wxss后缀改为less,然后拷贝到mini-demo -> src的目录下,并在根目录下npm init创建一个package.json文件,后面会安装各种构建依赖包。

通常来说,使用less都会创建variables.less及mixins.less文件,目前我想将这两个less样式文件约定,统一放到src目录下叫做styles的文件夹中,然后在工程构建中将这两个文件内容逐一添加进各个样式文件中。

image.png

到此,项目准备工作已经完成,接下来我们要做的就是构建工程代码实现:

  1. 监听src目录下的less样式文件改动,实时将less文件编译成css,并将文件后缀名重新改为wxss
  2. 将src文件整体输出到dist目录

创建build.js

在根目录下创建build.js,并在package.json script中添加脚本

"dev": "node build.js",
复制代码

后续我们通过npm run dev方式启动运行构建代码

编写build.js构建脚本

首先,启动npm run dev后,我们要实现:

  1. 文件监听功能,npm包:chokidar
  2. 文件操作的功能(如将src目录下文件移动到dist目录),npm包:fs-extra
  3. less编译:npm包:less
  4. 处理样式,npm包:postcss

以上相关包的用法请自行查阅文档,下面直接上代码,配合注释不难阅读:

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目录成功生成:

image.png

点开index.wxss,可以看到less文件成功编译:

image.png

源码地址

仓库源码以序号对应每篇文章源码

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享