使 Prettier 一键格式化 WXSS,我发现似乎还没有人做这这个事情?
发布于 4 年前 作者 vliang 4919 次浏览 来自 分享
本文将会结合 ESLint、Prettier、husky、lint-stage、gulp.js 等工具使得项目一键化操作,减少在格式化、代码检查等操作上浪费时间,因为大前端真的太多东西学了,不学会“偷懒”的话,我们就要落后更多了。

本系列文章的示例 Demo 在这里 👉 GitHub: wechat_applet_demo

分为两篇文章介绍:

使Prettier一键格式化WXSS(上集)
使Prettier一键格式化WXSS(下集)

强烈建议看我在简书更新的文章 👆,习惯在简书更新文章。微信社区发表文章使用 Markdown 用着不顺手,所以本文只做一个大概的简述。


一、前世今生

最近在做公司部门前端项目由 SVN 迁移 Git 的事情,由于历史代码在此之前并没有引入类似 ESLintPrettier 的代码检查或者格式约束等工具。

目前部门仅剩我一人维护这十几个小程序、H5 前端项目。现在只要接触以前那些没有经手的项目,就头疼不想改。虽然思想是这样,但很无奈,谁让我只是一个“打工仔”呢!

二、必备

创建小程序项目,使用 yarn 作为包管理工具、安装 vscode 相关插件。

三、配置 ESLint、Prettier

这些都不难了,很多人都懂了。还是那句话,看我上面的原文。

其实 ESLint、Prettier 在目前的 H5 项目中,几乎所有前端框架或库都兼容得很好了,一系列配套的工具简直用得不要太爽了。Prettier 支持 CSS、LESS、SCSS 等,但是呢,他遇到小程序的 wxss 或者 acss 却不行了,会报错:

[error] No parser could be inferred for file: app.wxss

原因是 Prettier 并没有解析器去解析它们,它不知道怎么处理,所以就抛出错误了。

这就是本文主要要解决的问题。在此之前,我是通过安装 vscode 插件 Prettier - Code formatter 一个一个来格式化的,太傻了。

四、如何让 Prettier 识别小程序的层叠样式呢?

此前我去网上搜索了一番,似乎真没有人去做这件事,也可能是没公开或者没写出来,反正我还没找到,哈哈。

我使用的是 Gulp.js 来处理。如果对 Gulp 不太熟悉了,点击这里了解一下。

简单说下 Gulp.js 的工作方式,它使用的是 Node.js 中的 stream(流),首先获取到需要的 stream,然后通过 stream 的 pipe() 方法把流导入到你想要的地方。比如 Gulp 插件中,经过插件处理后的流又可以导入到其他插件汇总,当然也可以把流写入文件中,所以 Gulp 是以 stream 为媒介的,它不需要频繁的生成临时文件,这也是 Gulp 的速度比 Grunt 快的一个原因。

下面我们只用到 Gulp 的其中两个 API, gulp.src() 和 gulp.dest()

思路:使用 gulp.src() 获取流,然后使用 Gulp 插件对流分别作重命名(gulp-rename)、格式化(gulp-prettier)、再重命名回来(gulp-rename)、最后导出(gulp.dest())。过程中有利用 gulp-debug 插件来查看一些信息。

// gulpfile.js
const { series, parallel, src, dest } = require('gulp')
const rename = require('gulp-rename')
const debug = require('gulp-debug')
const clean = require('gulp-clean')
const prettier = require('gulp-prettier')
const config = require('./.prettierrc')

// wxss 一键格式化
const wxssPrettier = () => {
  return src('./**/*.wxss')
    .pipe(
      // 可以利用插件,查看一些 debug 信息
      debug()
    )
    .pipe(
      // 重写扩展名为 css,才能被 Prettier 识别解析
      rename({
        extname: '.css'
      })
    )
    .pipe(
      // Prettier 格式化
      prettier(config)
    )
    .pipe(
      // 重新将扩展名改为 wxss
      rename({
        extname: '.wxss'
      })
    )
    .pipe(
      // 导出文件
      dest(__dirname)
    )
}

// acss 一键格式化
const acssPrettier = () => {
  return src('./**/*.acss')
    .pipe(debug())
    .pipe(
      rename({
        extname: '.css'
      })
    )
    .pipe(prettier(config))
    .pipe(
      rename({
        extname: '.acss'
      })
    )
    .pipe(dest(__dirname))
}

// 这里导出多个 task,通过 gulp xxx 就能来调用了,如 gulp all
// 关于 series、parallel API 分别是按顺序执行(同步)、同时执行(并行)
module.exports = {
  all: parallel(wxssPrettier, acssPrettier),
  wxss: wxssPrettier,
  acss: acssPrettier
}

调用 Gulp 任务:

// package.json
{
  "scripts": {
    "prettier:wxss": "gulp wxss",
    "prettier:accs": "gulp acss",
    "prettier:wxss:acss": "gulp all"
  }
}

五、Git-Hooks

利用 Git Hooks 钩子实现提交代码自动执行此前的 ESLint、Prettier 命令,以保证我们提交的代码是不丑的。

我们这里使用到的是 pre-commit。

六、husky

husky 是一个为 Git 客户端增加 hook 的工具。当其安装到所在仓库时,它会自动在 .git/hooks 增加相应的钩子实现在 pre-commit 阶段就执行一系列保证每一个 commit 的正确性。

当然,pre-commit 阶段执行的命令,当然要保证其速度不要太慢,每次 commit 都等很久也不是好的体验。

// package.json
{
  "husky": {
    "hooks": {
      "pre-commit": "yarn run format:all"
    }
  }
}

七、lint-staged

上面的流程,我们只提交了一个文件的变动,但是它对所有文件进行了扫描,这里是存在体验性问题的。

假如我们有 N 多个暂存文件,那么每当我们 git commit 一次就所有检查所有文件一遍,这导致我们的体验非常不好,过程很慢,显然不是我们想要的。

那么如何解决呢?我们需要用到它 👉 lint-staged

// package.json
{
  "husky": {
    "hooks": {
      "pre-commit": "lint-staged --config .lintstagedrc.js"
    }
  }
}
// .lintstagedrc.js
const path = require('path')

module.exports = {
  '*.js': ['prettier --config .prettierrc.js --write', 'eslint --fix --ext .js'],
  '*.json': 'prettier --config .prettierrc.js --write',
  '*.wxss': absolutePaths => {
    // 获取相对路径
    // const cwd = process.cwd()
    // const relativePaths = absolutePaths.map(file => path.relative(cwd, file))
    // return `gulp wxss --path ${relativePaths.join(' ')}`

    return 'gulp wxss'
  },
  '*.acss': 'gulp acss'
}

八、至此

上面介绍的都很粗糙,不完整。有兴趣的请看 👉 原文

1 回复
回到顶部