This article will incorporate tools like ESLint, Prettier, husky, lint-stage, gulp.js, etc., to make the project one-key and reduce the time wasted on formatting, code checks, etc., because there is so much to learn about the big front end, and if we don’t learn to “slacken”, we will fall further behind.

A sample Demo for this series is available here at 👉 GitHub: wechat_applet_demo.

It is divided into three articles:

  • PretTier to format WXSS with one click
  • PretTier to format WXSS with one click
  • PretTier to format WXSS with one click

There are also updates in Jane Books at 👉 here.

Recently, I am working on the front-end project of the company department to migrate Git from SVN, because the historical code did not introduce code checking or format constraint tools like ESLint and Prettier before this.

At present, I am the only one person in the department to maintain a dozen small programs and H5 front-end projects. Now as long as the contact before those unhandled projects, headache do not want to change. Although the thought is such, but very helpless, who let me just a “worker” it!

After the joke, get down to business.

For one,

1. Create a new WeChat applet project

This is too simple to omit 10,000 words…

# or wechat_applet_demo cloning project down $CD your_folder $git clone [email protected]: toFrankie/wechat_applet_demo git
2. Use yarn as a package management tool

YARN is not installed in this series, so I’m sure you all understand. And don’t go into details. Search for yourself.

3. Use Visual Studio Code as the editor

Although I’ve been in the business for a while, I’m sorry, I only use VS Code for front-end development, and I think I’ll be using it for a long time. – Webstorm, Atom, Sublime Text, etc. were used but no longer are.

Anyway, it doesn’t matter what development tools you’re comfortable with.

Here are a few VS Code plug-ins that are relevant to this project

ESLint: Automatically detects ESLint rules that do not conform to the rules and will be alerted to ️ on the edit page


Prettier-code formatter: Can be used for formatting

After following the above two plug-ins, you need to add some configuration to the editor.

Considering the multi-person development scenario, everyone has different development tool configuration, so I put the following configuration in the project root directory and add it to Git version control so that everyone gets the project with this configuration.

Path is: 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, // Whether to enable VsCode's eslint "eslint.options": Extensions: [".js", ".ts", ".tsx"]}, "eslint.validate": ["javascript"], "editor.codeActionsOnSave": { "source.fixAll.eslint": true }, "git.ignoreLimitWarning": true }

Two, it’s time to start

1. yarnInitialization generatespackage.json:

2. Install ESLint and Prettier dependencies

To use ESLint, there are often a lot of rules that need to be configured, which would obviously take a lot of effort if everyone had to do it. So someone stepped up and opened their code spec library on GitHub, popular ones being Airbnb, Standard, Prettier, etc.

Here I choose the eslint-config-alloy open source specification library produced by Tencent AlloyTeam in China.

In fact, their team used Airbnb rules at the beginning, but because it was too strict, some rules needed to be personalized, which led to more and more changes later, and finally decided to maintain a new set. After more than two years of polishing, ESlint-config-alloy is now very mature.

Several reasons why I chose it:

  • For React/Vue/ TypeScript projects
  • Styles-related rules are managed by Prettier
  • There are Chinese documentation and examples of websites (which fascinates me due to my poor level of English lol)
  • Updates are fast and there are officially maintained TypeScript rules for Vue, TypeScript and React + TypeScript
$yarn add --dev [email protected] $yarn add --dev script $yarn add --dev script $yarn add --dev script $yarn add --dev [email protected] $yarn add --dev startup $yarn add --dev dev dev dev dev $yarn add Yarn add - dev [email protected]
3. After installing the dependencies, add the configuration files for ESLint and Prettier

They can have a variety of configuration files, in JavaScript formats such as.eslintrc.js and.prettierrc.js, placed in the root of the project.

For the configuration I will not expand to say, if there is doubt, you can search for the answer or comment to me.

// .eslintrc.js
module.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.js module.exports = { printWidth: 120, tabWidth: 2, useTabs: false, semi: false, singleQuote: True, // The key of the object is used in quotes only if necessary. // JSX uses double quotes instead of single quotes: jSXSingleQuote: False, // end without comma trailingComma: 'none', // start and end within bracketSpacing bracketSpacing: true, // JSX tag end Angle brackets need to wrap JSXBracketSameLine: False, // ArrowParens: 'avoid', // Each file format range is the entire contents of the file rangeArt: 0, rangeEnd: Infinity, // No need to write @prettier requirePragma: false at the beginning of the file. // No need to automatically insert @prettier insertPragma at the beginning of the file: False, / / use the default fold line standard proseWrap: 'preserve, / / according to display style decided to don't fold line htmlWhitespaceSensitivity HTML: 'CSS ', // use lf endOfLine: 'lf'}
4. Configure ESLint, Prettier to ignore rules

The corresponding files are.eslintignore and.prettierIgnore, both of which are placed in the project root directory.

These are adjusted according to the actual situation of their own projects. The following is for reference only:

# .eslintignore

*.min.js
typings
node_modules
# .prettierignore

*.min.js
/node_modules
/dist
# OS
.DS_Store
.idea
.editorconfig
.npmrc
package-lock.json
# Ignored suffix
*.log
*.md
*.svg
*.png
*ignore
## Built-files
.cache
dist
5. Add.editorconfigThe configuration file

It is used to smooth out the differences between different editors. Also placed in the project root directory.

# .editorconfig # http://editorconfig.org # https://github.com/editorconfig/editorconfig/wiki/EditorConfig-Properties # If you find a file 'roor = true', you will no longer look for root = true # matches all files [*] # indent style: Charset = utf-8 charset = utf-8 charset = utf-8 Trim_trailing_whitespace = true # Add a blank line to the end of the file insert_final_newline = true # operator with space spaces_around_operators = true # both times [*.js] # string using single quotes quote_type = single [*.md] trim_trailing_whitespace = false
6. Add NPM scripts

Add three script directives:

  • "eslint": "eslint ./ --ext .js"
  • "eslint:fix": "eslint --fix ./ --ext .js"
  • "prettier:fix": "prettier --config .prettierrc.js --write './**/*.{js,css,less,scss,json}'"

With yarn run , you can perform one-click formatting and repair. Of course, ESLint can only fix part of the fix with –fix, and the rest has to be fixed manually.

{"name": "wechat_applet_demo", "version": "1.0.0", "description": "WeChat small program Demo", "main": "app.js", "repository": "[email protected]:toFrankie/wechat_applet_demo.git", "author": "Frankie <[email protected]>", "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": "" eslint 10.0.3", ":" 6.7.1 ", "eslint - config - alloy" : "3.7.1", "eslint - config - prettier" : "6.10.0", "eslint plugin - prettier" : "3.1.4", "prettier" : "at 2.0.5", "prettier - eslint - cli" : "5.0.0}}"

Three, you think it’s over?

Before moving on, it’s worth noting:

The next step in gulp.js is to let the Prettier process the CSS converted by gulp.js so that the final Prettier formats the WXSS.

But I did take a bit of a detour by specifying a file with an extension like.wxss to use the specified parser with the Prettier Configuration Overrides Configuration. In other words, we can use the CSS parser to process the.wxss file when we process it. (See the end of the series for more details.)

But my advice is to read the first two books and then read the final one.

No, no, no, no, no, no, no, no, no, no, no, no, no, no, no, no, no, no, no, no, no, no, no, no, no, no.

PretTier supports code formatting for JavaScript, JSX, Angular, Vue, Flow, TypeScript, CSS, LESS, SCSS, HTML, JSON, GraphQL, Markdown (GFM, MDX), YAML.

But it doesn’t recognize the cascading styles that are unique to small programs like WXSS and ACSS, and although they have the same rules as CSS, PretTier doesn’t have a parser to parse them.

We are trying to adjust the script command to (add file with *.wxss extension) :

{
  "scripts": {
    "prettier:fix": "prettier --config .prettierrc.js --write './**/*.wxss'",
  }
}

Then it will return an error like this:

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

Since that doesn’t work, you can’t just use VS Code’s Prettier plugin to format *. WXSS files one by one. That would be too much work to be “lazy”.

So what’s the solution?

I use gulp.js to handle this. If you’re not familiar with Gulp, check it out here.

Four, Gulp. Js

To briefly describe how gulp.js works, it uses the stream from Node.js, fetches the stream you want, and then imports the stream to where you want it via the pipe() method of the stream. In Gulp, streams can be imported into other plugins and written to files. As a result, Gulp operates on a stream and does not need to generate temporary files frequently. This is one reason why Gulp is faster than Grunt.

I started with this idea: first of all, I’m going to
wxss(
acss) and export as
css, and then delete
wxss(
acss), and then Prettier
cssFormat the file and go back
wxss(
acss) and then delete it
cssFile. This process frequently generates temporary files, a bit like Grunt.

However, after understanding the idea of Gulp, in fact, it helps us to avoid the link of adding and deleting files frequently, and to operate all files in memory, which will be faster, so I rejected the previous scheme.

Here we only use two of Gulp’s APIs, gulp.src() and gulp.dest().

1. gulp.src()

This method is used to retrieve a stream, but it is important to note that the contents of this stream are not the original file stream, but rather a virtual file object (Vinyl Files), in which the path, file name, contents, etc. of the original file are stored. (Here is not in-depth, point to stop, interested in their own understanding)

Syntax: gulp.src(globs[, options])

  • Globs: is the file matching mode used to match the file path (including the file name)
  • Options: is an optional parameter that we do not normally need

* See documentation for parameter details.

2. gulp.dest()

This method is used to write files

gulp.dest(path[, options])

  • Path: is the path to write to the file
  • Options: is an optional parameter that we do not normally need

To use gulp.dest() properly, you need to understand the relationship between the path parameters passed to it and the resulting file.

The flow of Gulp is generally as follows: The gulp.src() method is used to fetch the file stream we want to process. The pipe() method is used to import the file stream into gulp. The pipe() method is used to import the gulp stream into gulp.dest(). The gulp.dest() method writes the contents of the stream to a file.

Here need to figure out that we offered to gulp. The dest () was introduced into the path of the parameters, can only be used to specify which file to generate a directory, and cannot generate the specified file filename, it generated file filename used is imported into its file stream its file name, so the generated file name is determined by the import to its file streams, Even if we pass it a path parameter with a filename, then it will treat the filename as the directory name, for example:

Const gulp = require('gulp') gulp.src('script/jquery.js').pipe(gulp.dest('dist/foo.js')) // Dist /foo.js/jquery.js, not dist/foo.js

If you want to change the file name, you need to use the gulp-rename plugin.

  • The above API and method description for Gulp is based on official documentation and an article from the same source.

Five, start configuration

First, install Gulp dependencies.

$yarn add --dev [email protected] $yarn add --dev release $yarn add --dev release $yarn add --dev [email protected] $yarn add --dev

Next, we create a gulpfile.js file in the project root directory.

The quick start to gulp.js is simple and won’t be repeated here.

Ideas: Use
gulp.src()Get the stream and then use the Gulp plugin to rename the stream (gulp-rename), format the stream (
gulp-prettier), then rename it back (
gulp-rename), and finally export (
gulp.dest()). It is used in the process
gulp-debugPlug-in to view some information.

Here I to WeChat small program, pay treasure small program cascading style has dealt with.

// 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 wxsRetTier = () => {return SRC ('./**/*.wxss').pipe(const wxsRetTier = () => {return SRC ('. Rename ({extname: '.css'})).pipe(// Prettier format Prettier (config)).pipe(// reset the extension to 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))} Exports = {all:}; exports = {all:}; exports = {all: parallel(wxssPrettier, acssPrettier), wxss: wxssPrettier, acss: acssPrettier }

Call it in the following way

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

Execute the command, and we see the following result, indicating that the configuration was successful.

Six, the Git – Hooks

WXSS, ACSS extension of the above has been implemented to format the file with a key.

To get even lazier, with git-hooks we can implement ESLint, Prettier, and format the project before commit, and then stop the commit if an error occurs.

Since this article is already a long one, let’s move on to the next one…

Seven, a digression

Because the NPM package for this project is only used for code inspection and formatting, it does not participate in the page code logic. So I added the package configuration option to the applet local project configuration file.

PackOptions is used to configure options for the project during the packaging process. Packaging is a necessary step for previewing and uploading your project.

You can now specify the packoptions.ignore field to configure packaging to ignore files or folders that meet the specified rules, so that they will not appear in the preview or uploaded results.

Note that Alipay applet does not support options like Ignore at the time of writing this article.

// project.config.js
{
  "packOptions": {
    "ignore": [
      {
        "type": "regexp",
        "test": "\\.md$"
      },
      {
        "type": "folder",
        "test": "node_modules"
      }
    ]
  }
}