HBuilderX创建的uniapp项目配置UnoCSS

530 阅读6分钟

什么是UnoCSS

UnoCSS 是一个原子化 CSS 引擎 ,旨在提供一种高效、灵活且轻量级的方式来生成和管理 CSS 样式。它由 Anthony Fu(Vue.js 核心团队成员之一)开发,并作为现代前端开发中的一种创新工具。UnoCSS 的核心目标是通过高度可配置性和按需生成样式,减少冗余代码,同时保持高性能。

核心特点

  1. 原子化 CSS:UnoCSS 使用类似于 Tailwind CSS 的原子化类名模式,每个类名对应一个具体的样式规则
  2. 按需生成:UnoCSS 不会像传统框架那样预生成所有可能的样式规则,而是根据项目实际使用的类名动态生成所需的 CSS。
  3. 高度可配置:UnoCSS 提供了强大的配置能力,允许开发者自定义规则、主题和插件。
  4. 无预设(No Preset):UnoCSS 默认没有内置的样式规则或预设,完全依赖于开发者定义的规则。
  5. 支持多种框架:UnoCSS 可以与多种前端框架(如 Vue、React、Svelte 等)无缝集成,同时也支持纯 HTML 项目。
  6. 极快的构建速度:由于其按需生成的特性,UnoCSS 在开发和生产环境中都具有极高的性能表现。

对于我来说,使用 UnoCSS 终于不用再纠结类名了,对于需要经常切换主题的项目也非常友好。可以说,用过就回不去了!

所以,当我最近接手到一个uniapp项目后,马上决定引入 UnoCSS 进行开发。然而,按照网上的步骤操作后,发现配置无法生效。经过观察,发现大多数教程都是针对使用 CLI 创建的 uniapp 项目,而我这个项目是直接在 HBuilderX 中创建的,很多配置都被 HBuilderX 高度封装。你问我为什么要使用HBuilderX创建?不知道,因为项目不是我创建的。但我实在无法忍受想类名的烦恼,于是决定想办法引入 UnoCSS。终于,受到这篇文章的启发,使用unocss/cli + child_process.exec实现了 UnoCSS 的引入。

开始配置

1. 安装依赖包

pnpm i unocss unocss-preset-weapp -D

2. 创建uno.config.js

在项目根目录下创建 uno.config.js 文件,并添加以下配置:

import presetWeapp from 'unocss-preset-weapp'
import { defineConfig } from 'unocss'
import { extractorAttributify, transformerClass } from 'unocss-preset-weapp/transformer'
const { transformerAttributify, presetWeappAttributify } = extractorAttributify()
export default defineConfig({
  presets: [
    // https://github.com/MellowCo/unocss-preset-weapp
    presetWeapp({
      // h5兼容
      // 只开发小程序可删除
      platform: 'uniapp',
      isH5: process.env.UNI_PLATFORM === 'h5',
    }),

    // attributify autocomplete
    presetWeappAttributify(),
  ],
  transformers: [
    // https://github.com/MellowCo/unocss-preset-weapp/tree/main/src/transformer/transformerAttributify
    transformerAttributify(),
    // https://github.com/MellowCo/unocss-preset-weapp/tree/main/src/transformer/transformerClass
    transformerClass(),
  ],
})

3. 新增unocss/cli脚本

在 package.json 中新增 unocss/cli 脚本:

  "scripts": {
    "unocss": "unocss ./**/*.vue -c unocss.config.js --watch -o unocss.css",
    "unocss:build": "unocss ./**/*.vue -c unocss.config.js -o unocss.css"
  },

4. 引入unocss.css

在根组件 App.vue 中引入 unocss.css

<style>
    /* 每个页面公共 css */
    @import 'unocss.css'
</style>

至此,通过手动执行 pnpm unocss 命令,然后再启动项目,已经可以成功实现引入 UnoCSS 了。但每次启动项目前都需要手动执行脚本,这显然不够方便。

5. 实现自动化

为了实现自动化,我们可以通过 child_process.exec 在项目启动时自动执行 unocss 脚本。新建 vue.config.js 文件,并添加以下代码:

const { exec } = require('child_process');
console.log("process.env.NODE_ENV:", process.env.NODE_ENV);
console.log("当前nodejs版本", process.version);
const isDev = process.env.NODE_ENV === 'development';
exec(
    // 这里指令对应 package.json 中的 npm scripts  
    isDev ?
    'npm run unocss' :
    'npm run unocss:build', {
        cwd: __dirname, // 切换目录到当前项目,必须  
        stdio: 'inherit',
    },
    (error, stdout, stderr) => {
        // unocss --watch 是一个持久进程,不会立即执行回调  
        if (error) {
            console.error('[unocss] 异常,请检查');
            console.error(error);
            console.error(stdout);
            console.error(stderr);
        }

    })
module.exports = {};

通过以上配置,启动项目时会自动执行 unocss 脚本,从而实现 UnoCSS 的自动化引入。

正当我以为能够完结撒花时,意外来了!

意料之外

当时,经过以上步骤,我已经在常用电脑上成功配置并运行了项目。然而,当我在另一台电脑上尝试运行同一个项目时,却遇到了一个令人困惑的错误:'npm'不是内部或外部命令,也不是可运行的程序或批处理文件。。这让我感到非常奇怪,因为我确认已经安装了 node 和 npm,并且在本地终端中也能正常执行这些命令。

经过一番排查,我发现了一个关键问题:在 powershell 终端中,npm 命令可以正常执行,但在 cmd 中却失败了。而 child_process.exec 默认使用的是 cmd 来运行命令。于是,我开始深入探究为什么在 cmd 中无法运行 npm

最终,我找到了问题的根源:我的备用电脑在安装 fnm(Fast Node Manager)时,配置没有完全生效,导致 cmd 无法识别 npm 命令。为什么我的常用电脑没有这个问题呢?因为常用电脑上安装的是 nvm for windows,而 nvm 和 fnm 的实现原理不同,nvm 的环境变量配置在 cmd 中能够正常生效,因此常用电脑没有问题。

于是,我按照 fnm 的官方文档重新配置了环境变量,并在 cmd 中验证了 npm 命令可以正常执行。本以为问题已经解决,但当我满怀希望地启动项目时,却再次遇到了同样的错误:'npm'不是内部或外部命令,也不是可运行的程序或批处理文件。

经过进一步的分析,我得出结论:fnm 的官方文档中提到的配置方式,是通过为 cmd 添加一段启动脚本,使得每次打开新的命令提示符窗口或切换目录时,自动更新 fnm 的环境变量,从而让 fnm 正常工作。然而,这种启动脚本仅对用户手动启动的 cmd 生效,而对于通过 child_process.exec 启动的 cmd,这些脚本并不会被执行。因此,尽管在手动打开的 cmd 中 npm 可以正常运行,但在子进程中依然无法识别 npm 命令。

至此我已尝试过多种方法都无济于事。

失败案例:

  1. 按照官方文档配置脚本
  2. child_process.exec执行npm前显式运行启动脚本
  3. 通过在注册表写入启动脚本
  4. ......不一一列举,如有成功案例,希望大佬能分享一下

最终,我决定放弃在 cmd 中解决这个问题,转而让子进程直接使用 powershell 来执行 npm 命令。

当我加上shell: 'powershell.exe'后,启动项目,成功运行!

其他

在排查问题过程中,我发现子进程打印中文会出现乱码现象,以下方法能够解决

  1. 安装依赖包
pnpm i iconv-lite
  1. 配置
const { exec } = require('child_process');
const iconv = require('iconv-lite');
const encoding = 'cp936';
const binaryEncoding = 'binary';

exec(
    'xxx', {
        cwd: __dirname, // 切换目录到当前项目,必须  
        encoding: 'binaryEncoding',
        env: process.env,
        shell: 'powershell.exe'
    },
    (error, stdout, stderr) => {
        console.log(iconv.decode(new Buffer(stderr, binaryEncoding), encoding));
    })

以上就是我在 HBuilderX 创建的 uniapp 项目中配置 UnoCSS 的经历。

如果在配置过程中发现任何问题,或者文章中有不准确的地方,欢迎在评论区指正和讨论。我会尽力解答大家的疑问,并不断完善这篇文章。

感谢阅读!如果你觉得这篇文章对你有帮助,欢迎点赞、收藏或分享给更多有需要的开发者。