本文将会联合 ESLint、Prettier、husky、lint-stage、gulp.js 等工具使得我的项目一键化操作,缩小在格式化、代码查看等操作上浪费时间,因为大前端真的太多货色学了,不学会“偷懒”的话,咱们就要落后更多了。
本系列文章的示例 Demo 在这里 ???? GitHub: wechat_applet_demo。
分为两篇文章介绍:
- 使Prettier一键格式化WXSS(上集)
- 使Prettier一键格式化WXSS(下集)
在简书也有更新 ???? 这里。
最近在做公司部门前端我的项目由 SVN 迁徙 Git 的事件,因为历史代码在此之前并没有引入相似 ESLint、Prettier 的代码查看或者格局束缚等工具。
目前部门仅剩我一人保护这十几个小程序、H5 前端我的项目。当初只有接触以前那些没有经手的我的项目,就头疼不想改。尽管思维是这样,但很无奈,谁让我只是一个“打工仔”呢!
吐槽完,入正题。
一、必备
1. 新建一个微信小程序我的项目
此处过于简略省略一万字...
# 或者克隆 wechat_applet_demo 我的项目下来$ cd your_folder$ git clone git@github.com:toFrankie/wechat_applet_demo.git
2. 应用 yarn 作为包管理工具
yarn
相干的装置不在本系列教程,置信你们都懂。也不再赘述,自行搜寻。
3. 应用 Visual Studio Code 作为编辑器
尽管从业有一段时间了,不好意思,前端开发我只用 VS Code,未来好长一段时间应该还是它。至于什么 WebStorm、Atom、Sublime Text 等,用过但当初曾经不会了。
Anyway,什么开发工具不重要,本人用着难受就好。
上面介绍几个与本我的项目相干的 VS Code 插件
ESLint:自动检测 ESLint Rule,不合乎规定时,在编辑页面会有正告 ️
Prettier - Code formatter:可用于格式化
依照以上两个插件之后,须要对编辑器做增加一些配置。
思考到多人开发的场景,而每个人的开发工具配置不尽相同,所以我把以下配置放到我的项目根目录下中,并将其退出 Git 版本控制中,这样每个人拿到我的项目都有此配置了。
门路是:your_project/.vscode/settings.json
{ "files.associations": { "*.wxss": "css", "*.wxs": "javascript", "*.acss": "css", "*.axml": "html", "*.wxml": "html", "*.swan": "html" }, "files.trimTrailingWhitespace": true, "eslint.workingDirectories": [{ "mode": "auto" }], "eslint.enable": true, // 是否开启 vscode 的 eslint "eslint.options": { // 指定 vscode 的 eslint 所解决的文件的后缀 "extensions": [".js", ".ts", ".tsx"] }, "eslint.validate": ["javascript"], "editor.codeActionsOnSave": { "source.fixAll.eslint": true }, "git.ignoreLimitWarning": true}
二、要开始了
1. yarn
初始化生成 package.json
:
2. 装置 ESLint、Prettier 相干依赖
若要应用 ESLint,往往须要配置很多繁冗的 rules 规定,如果每个人都要这种做的话,显然会消耗很多精力。于是就有人站了进去,并在 GitHub 上开源了他们的代码标准库,比拟风行的有 airbnb、standard、prettier 等。
在这里我抉择的是国内腾讯 AlloyTeam 团队出品的 eslint-config-alloy 开源标准库。
其实他们团队最开始应用 Airbnb 规定,然而因为它过于严格,局部规定还是须要个性化,导致起初越改越多,最初决定从新保护一套。通过两年多的打磨,当初 eslint-config-alloy 曾经十分成熟了。
我抉择它的几点起因:
- 实用于 React/Vue/Typescript 我的项目
- 款式相干规定由 Prettier 治理
- 有中文文档和网站示例(就我那糟糕的英语水平,这点极吸引我,哈哈)
- 更新快,且领有官网保护的 vue、typescript、react+typescript 规定
$ yarn add --dev babel-eslint@10.0.3$ yarn add --dev eslint@6.7.1$ yarn add --dev eslint-config-alloy@3.7.1$ yarn add --dev eslint-config-prettier@6.10.0$ yarn add --dev eslint-plugin-prettier@3.1.4$ yarn add --dev prettier@2.0.5$ yarn add --dev prettier-eslint-cli@5.0.0
3. 装置完依赖,那么就要加上 ESLint、Prettier 的配置文件
他们的配置文件能够有多种,这里应用 JavaScript 格局别离是 .eslintrc.js
、.prettierrc.js
,都搁置在我的项目根目录下。
对于配置我就不开展说了,若有纳闷的,能够自行搜寻查找答案或者评论留言给我。
// .eslintrc.jsmodule.exports = { root: true, parser: 'babel-eslint', env: { browser: true, es6: true, node: true, commonjs: true }, extends: ['alloy'], plugins: ['prettier'], globals: { Atomics: 'readonly', SharedArrayBuffer: 'readonly', __DEV__: true, __WECHAT__: true, __ALIPAY__: true, App: true, Page: true, Component: true, Behavior: true, wx: true, my: true, swan: true, getApp: true, getCurrentPages: true }, parserOptions: { ecmaVersion: 2018, sourceType: 'module' }, rules: { 'no-debugger': 2, 'no-unused-vars': 1, 'no-var': 0, 'no-param-reassign': 0, 'no-irregular-whitespace': 0, 'no-useless-catch': 1, 'max-params': ['error', 3], 'array-callback-return': 1, eqeqeq: 0, indent: ['error', 2, { SwitchCase: 1 }] }}
// .prettierrc.jsmodule.exports = { printWidth: 120, tabWidth: 2, useTabs: false, semi: false, singleQuote: true, // 对象的 key 仅在必要时用引号 quoteProps: 'as-needed', // jsx 不应用单引号,而应用双引号 jsxSingleQuote: false, // 开端不须要逗号 trailingComma: 'none', // 大括号内的首尾须要空格 bracketSpacing: true, // jsx 标签的反尖括号须要换行 jsxBracketSameLine: false, // 箭头函数,只有一个参数的时候,无需括号 arrowParens: 'avoid', // 每个文件格式化的范畴是文件的全部内容 rangeStart: 0, rangeEnd: Infinity, // 不须要写文件结尾的 @prettier requirePragma: false, // 不须要主动在文件结尾插入 @prettier insertPragma: false, // 应用默认的折行规范 proseWrap: 'preserve', // 依据显示款式决定 html 要不要折行 htmlWhitespaceSensitivity: 'css', // 换行符应用 lf endOfLine: 'lf'}
4. 配置 ESLint、Prettier 疏忽规定
对应的文件是 .eslintignore
、.prettierignore
,同样的都放在我的项目根目录下。
这些就依据本人我的项目理论状况做调整了,以下仅供参考:
# .eslintignore*.min.jstypingsnode_modules
# .prettierignore*.min.js/node_modules/dist# OS.DS_Store.idea.editorconfig.npmrcpackage-lock.json# Ignored suffix*.log*.md*.svg*.png*ignore## Built-files.cachedist
5. 增加 .editorconfig
配置文件
它是用来抹平不同编辑器之间的差别的。同样搁置在我的项目根目录下。
# .editorconfig# http://editorconfig.org# https://github.com/editorconfig/editorconfig/wiki/EditorConfig-Properties# 根目录的配置文件,编辑器会由当前目录向上查找,如果找到 `roor = true` 的文件,则不再查找root = true# 匹配所有的文件[*]# 缩进格调:spaceindent_style = space# 缩进大小 2indent_size = 2# 换行符 lfend_of_line = lf# 字符集 utf-8charset = utf-8# 不保留行末的空格trim_trailing_whitespace = true# 文件开端增加一个空行insert_final_newline = true# 运算符两遍都有空格spaces_around_operators = true# 对所有的 js 文件失效[*.js]# 字符串应用单引号quote_type = single[*.md]trim_trailing_whitespace = false
6. 增加 npm scripts
增加三条脚本指令:
"eslint": "eslint ./ --ext .js"
"eslint:fix": "eslint --fix ./ --ext .js"
"prettier:fix": "prettier --config .prettierrc.js --write './**/*.{js,css,less,scss,json}'"
通过 yarn run <command>
即可执行一键格式化和修复了,当然了 ESLint 应用 --fix
只能修复一部分,残余的只能手动解决了。
{ "name": "wechat_applet_demo", "version": "1.0.0", "description": "微信小程序 Demo", "main": "app.js", "repository": "git@github.com:toFrankie/wechat_applet_demo.git", "author": "Frankie <1426203851@qq.com>", "license": "MIT", "private": true, "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "eslint": "eslint ./ --ext .js", "eslint:fix": "eslint --fix ./ --ext .js", "prettier:fix": "prettier --config .prettierrc.js --write './**/*.{js,css,less,scss,json}'" }, "devDependencies": { "babel-eslint": "10.0.3", "eslint": "6.7.1", "eslint-config-alloy": "3.7.1", "eslint-config-prettier": "6.10.0", "eslint-plugin-prettier": "3.1.4", "prettier": "2.0.5", "prettier-eslint-cli": "5.0.0" }}
三、你认为完了?
不不不,本文我最想分享的是上面这个,后面的内容都比较简单,很多人都懂了。
Prettier 反对的 JavaScript、JSX、Angular、Vue、Flow、TypeScript、CSS、Less、Scss、HTML、JSON、GraphQL、Markdown(GFM、MDX)、YAML 的代码格式化。
但其实是不能辨认 wxss
、acss
等小程序特有的层叠款式,只管它们规定与 CSS 无异,然而 Prettier 并没有解析器去解析它们。
咱们试图去调整脚本命令为(增加 *.wxss
扩展名的文件):
{ "scripts": { "prettier:fix": "prettier --config .prettierrc.js --write './**/*.wxss'", }}
而后去执行的时候就会报错,如下:
[error] No parser could be inferred for file: app.wxss
既然这样走不通的话,总不能利用 VS Code 的 Prettier 插件一个一个地去格式化 *.wxss
的文件吧,那样工作量太大了,不合乎咱们“偷懒”的做法。
那么如何解决呢?
我应用的是 Gulp.js 来解决。如果对 Gulp 不太熟悉了,点击这里理解一下。
四、Gulp.js
简略说下 Gulp.js 的工作形式,它应用的是 Node.js 中的 stream
(流),首先获取到须要的 stream
,而后通过 stream
的 pipe()
办法把流导入到你想要的中央。比方 Gulp 插件中,通过插件解决后的流又能够导入到其余插件汇总,当然也能够把流写入文件中,所以 Gulp 是以 stream
为媒介的,它不须要频繁的生成临时文件,这也是 Gulp 的速度比 Grunt 快的一个起因。
我刚开始时的想法是:首先将wxss
(acss
)转换并导出为css
,接着删除wxss
(acss
)文件,再者应用 Prettier 对css
文件进行格式化,转回wxss
(acss
)之后,再删除掉css
文件。这个过程会频繁的生成临时文件,思路是有点像 Grunt。然而理解了 Gulp 的思维后,其实它帮咱们省掉了频繁增删文件的环节,全副放在内存中操作,也会更快一些,所以此前的计划被我否掉了。
上面咱们只用到 Gulp 的其中两个 API, gulp.src()
和 gulp.dest()
。
1. gulp.src()
这个办法是用来获取流的,但要留神这个流外面的内容不是原始的文件流,而是一个虚构文件对象流(Vinyl files),这个虚构文件对象中存储着原始文件的门路、文件名、内容等信息。(这里不深刻,点到为止,有趣味自行理解)
语法:gulp.src(globs[, options])
- globs:是文件匹配模式,用来匹配文件门路(包含文件名)
- options:为可选参数,通常状况咱们不须要用到
*对于参数具体阐明,请看文档。
2. gulp.dest()
该办法是用来写文件的
gulp.dest(path[, options])
- path:是写入文件的门路
- options:为可选参数,通常状况咱们不须要用到
要想应用好 gulp.dest()
这个办法,就要了解给它传入的门路参数与最终生成的文件的关系。
Gulp 的应用流程个别是:首先通过 gulp.src()
办法获取到咱们想要解决的文件流,而后把文件流通过 pipe()
办法导入到 Gulp 的插件中,最初把通过插件解决后的流再通过 pipe()
办法导入到 gulp.dest()
中,gulp.dest()
办法则把流中的内容写入到文件中。
这里须要弄清楚的一点是,咱们给 gulp.dest()
传入的门路参数,只能用来指定要生成的文件的目录,而不能指定生成文件的文件名,它生成文件的文件名应用的是导入到它的文件流本身的文件名,所以生成的文件名是由导入到它的文件流决定的,即便咱们给它传入一个带有文件名的门路参数,而后它也会把这个文件名当做是目录名,例如:
const gulp = require('gulp')gulp.src('script/jquery.js').pipe(gulp.dest('dist/foo.js'))// 最终生成的文件门路为 dist/foo.js/jquery.js,而不是 dist/foo.js
若须要批改文件名,须要应用插件 gulp-rename。
- 对于上述 Gulp 的 API 与办法阐明,次要参考自官网文档与无双的一篇文章。
五、开始配置
首先,装置 Gulp 相干依赖包。
$ yarn add --dev gulp@4.0.2$ yarn add --dev gulp-clean@0.4.0$ yarn add --dev gulp-debug@4.0.0$ yarn add --dev gulp-prettier@3.0.0$ yarn add --dev gulp-rename@2.0.0
接着,咱们在我的项目根目录下创立一个 gulpfile.js
文件。
Gulp.js 官网疾速入门的教程,很简略,这里不在赘述。
思路:应用gulp.src()
获取流,而后应用 Gulp 插件对流别离作重命名(gulp-rename)、格式化(gulp-prettier
)、再重命名回来(gulp-rename
)、最初导出(gulp.dest()
)。过程中有利用gulp-debug
插件来查看一些信息。
这里我对微信小程序、支付宝小程序的层叠款式都解决了。
// gulpfile.jsconst { 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}
通过以下形式调用就好了
// package.json{ "scripts": { "prettier:wxss": "gulp wxss", "prettier:accs": "gulp acss", "prettier:wxss:acss": "gulp all" }}
执行命令,咱们看到如下后果,阐明配置胜利了。
六、Git-Hooks
下面曾经实现了对 wxss
、acss
扩展名的文件进行一键格式化了。
还能够“更懒”一些,利用 git-hooks 咱们可实现在 commit
之前,对我的项目进行 ESLint、Prettier 检测和格式化,一旦呈现谬误,将进行 commit
操作。
因为本文篇幅曾经很长了,所以咱们放到下一篇持续写...
七、插个题外话
因为本我的项目的 npm 包仅用于代码查看与格式化,并未参加页面代码逻辑中。所以我在小程序本地我的项目配置文件中增加上打包配置选项。
packOptions 用以配置我的项目在打包过程中的选项。打包是预览、上传时对我的项目进行的必须步骤。目前能够指定
packOptions.ignore
字段,用以配置打包时对合乎指定规定的文件或文件夹进行疏忽,以跳过打包的过程,这些文件或文件夹将不会呈现在预览或上传的后果内。
*须要留神的是支付宝小程序,在编写本文时还未反对相似 ignore
选项。
// project.config.js{ "packOptions": { "ignore": [ { "type": "regexp", "test": "\\.md$" }, { "type": "folder", "test": "node_modules" } ] }}