Objective: To build my React component library from scratch and get familiar with front-end engineering

Front-end engineering

Front-end engineering is a means of using tools to improve efficiency and reduce costs in accordance with certain standards and specifications.

Because some tools are too powerful at this stage, such as Webpack, many people mistakenly think engineering is Webpack. Such tools are not the core of engineering. The core of engineering should be a planning or architecture of the project as a whole, and tools are only a means to implement such planning and architecture in this process.

Refer to this article

Compare Webpack and gulp

Gulp is designed to standardize the front-end development process, focusing on the control and management of the whole process of front-end development (like pipelinization). We can configure tasks that are not properly configured in gulp (through gulp.task() method in gulP). Such as starting server, sASS /less precompilation, file consolidation and compression, etc.) to allow gulP to implement different functions to build the whole front-end development process.

Webpack is more focused on module packaging, of course, we can put all resources in development (pictures, JS files, CSS files, etc.) can be regarded as modules, Webpack is processed by loader and plugins on resources, but some file compression, consolidation, pre-processing and other functions, It’s just a feature that comes with it.

For a large project, it makes more sense for individuals to build front-end engineering solutions around GULp while also introducing WebPack to manage modular code

Gulp: handle HTML, CSS compression/preprocessing/conditional compilation, image compression, Sprite image automatic merge and other tasks.

Webpack: Manages modularity and builds JS

At the same time, I don’t like webpack to do other things besides JS, including packing CSS,copy and so on. I don’t deny the power of Webpack, but I still prefer to specialize,webpack is only responsible for JS related things. So webpack is responsible for es6-> ES5, esLint detection,js sourcemap file generation.

Webpack vs. Rollup

Both rollup and Webpack are modular packaging tools.

Projects (especially class libraries) only have JS and no other static resource files, so using WebPack is a bit too big to use because webPack bundles are a bit bigger, slower, and less readable.

Webpack and Rollup can be used to their advantage in different scenarios. Webpack has “inherent advantages” for code splitting and static resource import, and supports hot module replacement (HMR), which Rollup does not, so consider Webpack when your project needs these. However, Rollup has algorithmic advantages for tree-shaking code and ES6 modules. If your project only needs to be packaged as a simple bundle and is developed based on ES6 modules, consider using Rollup. Webpack supports tree-shaking since 2.0 and supports packaging of ES6 modules with Babel-Loader. In fact, Rollup is losing its edge. However, it has not been abandoned. Instead, it is favored by many library developers due to its simple API and usage. React, Vue, etc., all use Rollup as a build tool. Webpack is now widely used in medium and large projects. Finally, in one sentence: Use Webpack for application development and Rollup for library development.

Project introduction

Gulp is responsible for the package compilation of the component library, webpack is responsible for the display of the component library instance. After the completion of the component library, online documents will be used together.

Webpack configuration

Webpack-cli and webpack-dev-server are incompatible.

error: Cannot find module ‘webpack-cli/bin/config-yargs’,

Solutions: 1, modify package. The script in json "dev" : "webpack serve - config config/webpack development. Js - open" configuration file path changes 2. Uninstall webpack-cli NPM uninstall webpack-cli NPM install [email protected] -dCopy the code

Eslint-webpack-plugin comes with ESLint checking

plugins: [
    new ESLintPlugin({
      extensions: [".tsx", ".ts", ".js"]
    })
]
Copy the code

Note that I didn’t configure extensions in the beginning, so it wasn’t checked when webPack was packaged.

Webpack’s resolve property configuration

resolve: { alias: { "bufang-ui": path.resolve(__dirname, ".. / components ")}, / / path alias extensions: [", "benchmark" ts ", "js"] / / can omit filename suffix},Copy the code

Prettier configuration

Format your code style. This is very important. See this article

When I create the. Prettierrc file, I do the following:

{
  "singleQuote": false,
  "semi": true,
  "tabWidth": 2,
  "useTabs": false,
  "trailingComma": "none",
  "printWidth": 120,
  "jsxBracketSameLine": false,
  "overrides": [
    {
      "files": ".prettierrc",
      "options": { "parser": "json" }
    }
  ]
}

Copy the code

Eslint configuration

Refer to this article

Extends (extends)

An extension is a quick and easy way to use lint rules already written by someone else. Extensions generally support three types:

{
  "extends": [
    "eslint:recommended",
    "plugin:@typescript-eslint/recommended",
    "plugin:react/recommended"
  ]
}
Copy the code

Eslint: Starts with an official extension of ESLint. There are two: esLint :recommended, esLint: All. Plugin: Extensions are plugins and can also be set directly in plugins (this doesn’t seem to work, so we recommend introducing rules in this area). 3. The last type of extension comes from the NPM package. The NPM package extension must start with eslint-config-, which can be omitted. In the example above, eslint-config-standard can be simply shortened to standard. If you are satisfied with your configuration, you can also publish your Lint configuration to the NPM package.

Plugins

There are hundreds of rules to choose from, but that’s not enough, because the official rules only check standard JavaScript syntax, and if you’re writing JSX or Vue single-file components, ESLint’s rules start to fall into place. In this case, you need to install an ESLint plug-in to customize certain rules for checking. Plugins for ESLint have the same naming format as extensions, starting with eslint-plugin-, which can also be omitted when used.

npm install --save-dev eslint-plugin-vue eslint-plugin-react

{
  "plugins": [
    "react", // eslint-plugin-react
    "vue",   // eslint-plugin-vue
  ]
}
Copy the code

An extension is a plugin that loads the plugin.

{
  "extends": [
    "plugin:react/recommended",
  ]
}
Copy the code

Install the eslint-plugin-react package. Install the eslint-plugin-react package. Install the eslint-plugin-react package. So where does this configuration name come from? You can see the source code for eslint-plugin-react

Module. exports = {// custom rules: allRules, // configs: {// plugin:react/recommended recomended: {plugins: [ 'react' ] rules: {... } }, // plugin:react/all all: { plugins: [ 'react' ] rules: {... }}}}Copy the code

The configuration name is defined by the configs property of the plugin configuration, where the configuration is actually an extension to ESLint. This way plugins and extensions can be loaded.

Rules

Customize lint rules based on the actual team or project. These rules override the extends and plugins rules above, with maximum weight.

Rules: {"no-console": 1, // can be extended by the team or project itself.Copy the code

The runtime environment determines whether a rule is disabled

rules: {
    'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
    'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off'
},
Copy the code

Why @babel/eslint-parser

ESLint’s default parser and core rules only support the latest final ECMAScript standard and do not support experimental (such as new features) and non-standard (such as streams or TypeScript types) syntaxes provided by Babel. @babel/eslint-parser is a parser that allows ESLint to run on Babel transformed source code. ESLint allows the use of custom parsers. When using this plug-in, the code is parsed by Babel’s parser (using the configuration specified in the Babel configuration file) and the generated AST is converted into an ESTree compliant structure that ESLint can understand. All positional information, such as row numbers and columns, is also retained so that you can easily track errors.

See the description of NPM for details

Husky and lint – staged

Husky is a tool that adds hooks to Git clients. Once installed, it automatically adds hooks to the.git/ directory in your repository. For example, a pre-commit hook will trigger when you perform a Git commit. Lint-staged this means that the code inspected is only the code that has been updated this time, rather than the entire code

In order to ensure that the code we submit to GitLab is compliant with the company code specification, we will esLint the latest code before git commit. If ESLint reports an error, git commit will fail.

1. Install HusKY and Lint-staged

NPM install husky Lint-staged -D However, there was a problem with this: The latest version of Husky (5.1.3) did not respond to hooks fumping for half a day, I scaled it down to 4.3.6, and it worked. It is also possible that there are some configurations in the latest version that I did not configure and do not respond to hooks. (Wish there was a god to guide)Copy the code

Make sure that the message complies with the specification when git commit

npm install @commitlint/config-conventional @commitlint/cli -D
Copy the code

Commitlintrc.js file and commit Message rule

Const types = ["build", // modify the submit "CI" of the project's build system (XcodeBuild, Webpack, GLUP, etc.), // modify the submit "chore" of the project's continuous integration process (Kenkins, Travis, etc.), // Build process or assistiv changes "docs", // Documents "feat", // add feature "fix", // Fix bug "pref", // Add performance/experience related commit "refactor", // Code refactoring "revert", // rollback of an older submission "style", // code changes that do not affect application logic, mainly style improvements, changes to "test", // test-related development]; // Rule reference format is feat: Function Description Const typeEnum = {rules: {"type-enum": [2, "always", types],}, value: () => types,}; module.exports = { extends: ["@commitlint/config-conventional"], rules: { "type-case": [0], "type-empty": [0], "scope-empty": [0], "scope-case": [0], "subject-full-stop": [0, "never"], "subject-case": [0, "never"], "header-max-length": [0, "always", 72], "type-enum": typeEnum.rules["type-enum"], }, };Copy the code

4. Package. json configuration

"husky": { "hooks": { "pre-commit": "lint-staged", "commit-msg": "Commitlint-e HUSKY_GIT_PARAMS" // commit commit -m "feat: changed bug"}}, "lint-staged": { "src/**/*.{js,ts,tsx}": [ "eslint --fix", "prettier --write", "git add" ] }Copy the code

We checked the code twice. The first time was when webPack was packaged. If ESLint reported an error, the package would fail. The second time is git commit time. If ESLint reports an error, the commit will also be lost. In addition, during our coding process, we can also use the editor’s plug-in to do the initial inspection and formatting of the code. The overall result is three code reviews and formatting, which ensures that the code is normative and highly maintainable.

At this stage, the component library has just been built and there are no available components in it. The warehouse address