从混乱到秩序:微信小程序基于LESS的一致性编译策略

280 阅读3分钟

背景

在微信小程序的开发中,我们使用LESS进行样式开发,并通过easy-less编译成WXSS。然而,由于历史原因,有些开发者只修改了WXSS文件而没有同步更新对应的LESS文件。这导致在后续开发中,修改LESS文件会覆盖前一个开发者在WXSS文件中的样式,更严重地影响了项目的维护和更新。

问题描述

  • 样式不一致:由于直接修改WXSS文件,LESSWXSS文件之间缺乏一致性,导致样式管理混乱。😤
  • 代码覆盖:当有人修改LESS文件并重新编译时,会覆盖之前直接在WXSS文件中进行的修改,导致样式冲突和混乱。
  • 维护困难:由于无法直接从LESS文件反映WXSS文件的最新状态,维护和更新样式变得极为困难。

优化方案

1. 编译所有less成wxss

由于我们之前用的是easy-less的插件编译,所以为了保证wxss转换后的一致性。我在easy-less的源码中添加了一个新功能,该功能可以将项目下所有的LESS文件编译成对应的WXSS文件。顺便给该项目提交了一个PR哈哈哈哈。🥸

 // 在源码的/src/easyLess.ts
  // compile all less files in workspace
  const compileAllLessCommand = vscode.commands.registerCommand('extension.compileAllLess', async () => {
    const files = await vscode.workspace.findFiles('**/*.less', '**/node_modules/**');
    files.forEach(file => {
      vscode.workspace.openTextDocument(file).then(document => {
        new CompileLessCommand(document, lessDiagnosticCollection).setPreprocessors(preprocessors).execute();
      });
    });
  });
  
  context.subscriptions.push(compileAllLessCommand);
// package.json

"contributes": {
    "menus": {
      "editor/context": [
        {
          "command": "extension.compileAllLess",
          "group": "navigation"
        }
      ]
    },
    "commands": [
      {
        "command": "extension.compileAllLess",
        "title": "Compile All Less Files"
      }
    ],
 }

点击F5调试,打开项目目录,点击F1输入Compile All Less Files,或者右键选择。

image.png

2. 还原未被修改的LESS

借助VSCode的Git功能,对比这些编译生成的WXSS文件的变更情况。对于有改动的WXSS文件,就代表这个wxss文件被更改过。然后在对应的LESS文件上进行修改,确保所有的LESS和WXSS文件都可以一一对应。(从270几个文件中找到26个文件被修改过)😫😫

3. 删除WXSS文件

在确保所有的LESS和WXSS文件一一对应后,我将项目中的所有有LESS依赖的WXSS文件全部删除(因为有几个公用的样式文件是直接用WXSS写的)。之后,在小程序打包时才将WXSS文件从LESS文件编译出来。这样一来,项目中只保留LESS文件,避免了之前的样式冲突问题。

const fs = require('fs');
const path = require('path');

function deleteFile(filePath) {
  fs.unlink(filePath, (err) => {
    if (err) {
      console.error(`Error deleting file ${filePath}:`, err);
    } else {
      console.log(`File ${filePath} deleted.`);
    }
  });
}

function traverseDir(dir) {
  fs.readdir(dir, (err, files) => {
    if (err) {
      console.error(`Error reading directory ${dir}:`, err);
      return;
    }

    files.forEach((file) => {
      const filePath = path.join(dir, file);

      fs.stat(filePath, (err_, stats) => {
        if (err_) {
          console.error(`Error getting stats for file ${filePath}:`, err_);
          return;
        }

        if (stats.isDirectory()) {
          traverseDir(filePath);
        } else if (path.extname(filePath) === '.less') {
          const wxssFilePath = filePath.replace(/\.less$/, '.wxss');
          fs.access(wxssFilePath, fs.constants.F_OK, (err__) => {
            if (!err__) {
              deleteFile(wxssFilePath);
            }
          });
        }
      });
    });
  });
}

traverseDir('.');

4. 实时监听LESS文件变更,生成对应WXSS

由于我们项目是原生和Taro混编项目,在开发阶段需要监听原生项目的文件改动,并将改动的文件copy到dist文件夹内🤬。当LESS文件发生变更时,我会先把LESS文件copy到编译的文件夹中,然后直接利用gulp-less对less编译成wxss。(注意是在编译的文件夹中操作,不是在源码中) 确保了开发过程中样式文件的一致性和实时性。(此操作用的是chokidar进行监听)🤯

5. 使用Gulp在打包时编译LESS到WXSS

在打包过程中,我使用了Gulp进行自动化编译。Gulp会将项目中的LESS文件转换成WXSS文件,并将其放置在编译后的dist文件夹中对应的位置。

// gulpfile.js
const path = require('path')
const fs = require('fs')
const glob = require('glob')
var gulp = require('gulp') // 载入Gulp模块
var less = require('gulp-less') // 载入gulp-less模块
var cssnano = require('gulp-cssnano') //css优化分离
const rename = require('gulp-rename')

const rootPath = path.resolve(__dirname, './')
const distPath = path.join(rootPath, './dist/wxapp')  // 原生小程序项目打包后的目录
gulp.task('less', function () {
  return gulp
    .src([`${distPath}/**/*.less`])
    .pipe(less())
    .on('error', function (err) {
      console.error('Less compilation error:', err.message)
    })
    .pipe(
      cssnano({
        reduceIdents: false, // 不压缩动画名字
        autoprefixer: false, // 不需要自动前缀
        zindex: false, // 不压缩z-index
      }),
    )
    .on('error', function (err) {
      console.error('Cssnano error:', err.message)
    })
    .pipe(
      rename(function (_) {
        _.extname = '.wxss'
      }),
    )
    .pipe(gulp.dest(distPath))
    .on('error', function (err) {
      console.error('Gulp dest error:', err.message)
    })
    .on('end', function () {
      glob(`${distPath}/**/*.less`, (err, files) => {
        if (err) {
          console.error('Glob error:', err.message)
        } else {
          files.forEach((file) => {
            fs.unlinkSync(file)
            console.log(`Deleted ${file}`)
          })
        }
      })
    })
})

优化效果

项目在以下方面取得了显著改善:

  • 工具单一性:删除了无依赖的WXSS,只剩下LESS进行开发。🫡
  • 维护便利:以后所有样式修改都集中在LESS文件中,简化了维护工作。🫠

结论

通过此优化手段,终于解决了微信小程序开发中的样式管理的历史问题。此优化方案不仅提升了项目的开发效率,还确保了代码的一致性和可维护性。🫨😑

有更好方案或者有疑问的小伙伴欢迎在评论区留言