preface

This article abandoned the official recommended NPX create-react-app my-app scaffolding installation method, build your own environment, so that you have absolute control of your project, a comprehensive understanding of the project configuration file.

Abandon the official scaffolding and build the environment manually

Create a basic configuration file

Create a package.json file
  npm init -y
Copy the code
  • Introduction to Some Fields
    • Script: Running script commandsnpmCommand line abbreviations
    • Description: Indicates the description of the project
create.gitignore
  • This file determines which files or folders to ignore when your project commits to Git
  • Editors such as vscode also listen for all files except.gitignore
  • If a file that is not ignored changes, it will be recognized as a file that needs to be committed when git commits
create.npmrc
  • Create a file

      # powershell
      New-Item .npmrc
      # linux
      touch .npmrc
    Copy the code
  • Add configuration code to use Taobao mirror to speed up

      registry=https://registry.npm.taobao.org/
    Copy the code
createREADME.md

Standard code

Prettier of the code
  1. Standard code is very important, in the first place, a good project, must ensure the code quality, uniform code style

  2. Use Prettier to format code

  • Prettier-code formatter install prettier-code formatter in vscode

  • Install command

  npm install prettier -D
Copy the code
  • Create the.prettierrc.js file as defined by company rules
ArrowParens: 'avoid', // arrow functions with only one argument can ignore the parentheses bracketSpacing: true, // brackets should not appear inside the spacing endOfLine: 'lf', // use Unix format jsxBracketSameLine: false, // jsxSingleQuote: False, // JSX attribute use double quotation marks printWidth: 140, // line width proseWrap: 'preserve', // newline semi: true, // add semicolon at the end of a sentence: TabWidth: 2, // Indent useTabs: false, // Indent trailingComma with Spaces: // Add a space between the bracketons and the text of the object; // Print a semicolons at the end of the statementCopy the code
  • Create a settings.json file in the new.vscode folder. The configuration takes precedence over the editor’s global configuration

  • Ignore certain folders with.prettierIgnore

      /node_modules
      /build
      /dist
    Copy the code
  • Notes on NPM

    • npm install XXX -S
      • This setup is partial and will be in dependencie in package.json file
      • Dependencies: Indicates the dependency management in the production environment
    • npm install XXX -D
      • This setup is local and is written to devDependencies in package.json
      • DevDependencies: Describes dependency management in the development environment
      • If you install libraries that are used to package and parse code, such as Webpack or Babel, you can use -d to install them. Once the project goes live, these libraries will be useless
    • npm install XXX -g
      • Global installation. Once installed, it can be used elsewhere
    • npm install XXX
      • NPM install –save NPM install –save NPM install –save
Eslint for the code specification
  1. Eslint is primarily designed to address code quality issues, fixes can be made, and red lines can be prompted

  2. Using eslint

  • Install command

      npm install eslint -D
      npx eslint --init
    Copy the code
    • After executing the second command, you can select what you need
    • Install typescript to avoid errorsnpm install typescript -D
    • configure
      Specific can be set according to their own needsCopy the code
  • If you want to enable esLint auto repair, you can add the following code to setting.json in the.vscode folder in addition to vscode to have the same effect

    "eslint.validate": ["javascript", "javascriptreact", "typescript", "typescriptreact"], "typescript.tsdk": "./node_modules/typescript/lib", // instead of VSCode ts syntax smarts "editor.codeActionsOnSave": {" source.fixall.eslint ": true,},Copy the code
  • Ignore certain folders with.eslintignore

      /node_modules
      /build
      /dist
    Copy the code
Prettier conflicts with ESLint
  • Install the plugin eslint-config-prettier to disable the rule where Prettier conflicts with prettier

      npm install eslint-config-prettier -D
    Copy the code
  • Add the following code to the extends of.eslintrc.js

      'prettier'
    Copy the code
Eslint validates submitted code before submitting it
  1. Passage Ten formatted and ESLint validated the most recently modified files in git cache using Lint-staged and Husky
  • Install command
      npm install husky lint-staged -D
    Copy the code
  • Add the following configuration to package.json
"husky": { "hooks": { "pre-commit": "lint-staged" } }, "lint-staged": { "*.{ts,tsx,js}": ["eslint -- config.eslintrc.js "// --config specifies the configuration file to validate.ts.tsx.js in the temporary area, without --fix, Prevent the automatic repair unknown code], "*. {ts, the TSX, js, json, HTML, yml, CSS, less, SCSS, md}" : ["prettier --write" // --write code doesn't change syntax, automatic format can be added]}Copy the code
Verify the commit message
  1. The installationcommitlint
  • Install command
      npm install @commitlint/cli @commitlint/config-conventional -D
    Copy the code
  • Create the.commitlintrc.js file in the root directory and enter the following configuration
    module.exports = { extends: ['@commitlint/config-conventional'], rules: { 'type-enum': [ 2, 'always', ['build', 'ci', 'chore', 'docs', 'feat', 'fix', 'perf', 'refactor', 'revert', 'style', 'test', 'anno'], ,}}Copy the code
  • Configure the following code in package.json for husky
      {
        "husky": {
          "hooks": {
            "pre-commit": "lint-staged",
            "commit-msg": "commitlint --config .commitlintrc.js -E HUSKY_GIT_PARAMS"
          }
        },
      }
    Copy the code

Webpack configuration

Install webpack and webpack-CLI commands
  npm install webpack webpack-cli -D
Copy the code
Create config folder
  • Create constant.js under the folder to define public variables

    const path = require('path'); const PROJECT_PATH = path.resolve(__dirname, '.. / '); // Current project root directory const PROJECT_NAME = path.parse(project_path.name); module.exports = { PROJECT_PATH, PROJECT_NAME, };Copy the code
  • Create the webpack.common.js file in the folder and create the following code

  const path = require('path');
  const { PROJECT_PATH } = require('./constant');

  module.exports = {
    entry: {
      index: path.resolve(PROJECT_PATH, './src/index.tsx'),
    },
    output: {
      filename: 'js/[name].[hash:8].js',
      path: path.resolve(PROJECT_PATH, './dist'),
    },
  };
Copy the code
  • __dirnameThe absolute path on the computer that refers to the current folder
Add the command to the package.json script and execute it on the terminalnpm run bulidA file corresponding to the dist file is generated
  "build": "webpack --config ./scripts/config/webpack.common.js"
Copy the code
Distinguish between development and production environments
  • Install the webpack-merge command

      npm install webpack-merge -D
    Copy the code
    • Create the webpack.dev.js file in config to configure the development environment

        const { merge } = require('webpack-merge');
        const common = require('./webpack.common');
      
        module.exports = merge(common, {
          mode: 'development',
        });
      Copy the code
    • Create the webpack.prod.js file in config to configure the development environment

        const { merge } = require('webpack-merge');
        const common = require('./webpack.common');
      
        module.exports = merge(common, {
          mode: 'production',
        });
      Copy the code
  • Use cross-env to differentiate between development and production environments in a common configuration file

    • There is also an option for a certain configuration in the common configuration. Different configurations are used in the development environment and production environment. To avoid repetitive code writing, set environment variables
    • Cross-env can be set up and used across platforms, regardless of operating system differences
    • Install command
      npm install cross-env -D
    Copy the code
    • Modify the code in script in package.json
      "start": "cross-env NODE_ENV=development webpack --config ./scripts/config/webpack.dev.js",
      "build": "cross-env NODE_ENV=production webpack --config ./scripts/config/webpack.prod.js"
    Copy the code
    • Add variables to constants.js
    const isDev = process.env.NODE_ENV ! == 'production';Copy the code
    • This command is used to modify output in webpack.common.js. The hash value is used in the production environment but not in the development environment
      filename: `js/[name]${isDev ? ' ' : '.[hash:8]'}.js`,
    Copy the code
    • Devtool adds error messages

      • Add the code in webpack.dev.js
        devtool: 'cheap-module-source-map',
      Copy the code
      • The production environment does not require an error message. Set webpack.pord.js to None
        devtool: false,
      Copy the code
npm run startLive page appears
  • html-webpack-pluginAutomatically import packaged JS files into HTML files
  • webpack-dev-serverLocal HTTP service, through simple configuration can also specify its port, hot update enabled, and so on
  • Install command
      npm install webpack-dev-server html-webpack-plugin -D
    Copy the code
  • In the root directory, create the index.html file in the public folder and add plugin to webpck.common.js to import the index.html file
  plugins: [
    new HtmlWebpackPlugin({
      template: resolve(PROJECT_PATH, './public/index.html'),
      filename: 'index.html',
      cache: false,
      minify: isDev
        ? false
        : {
            removeAttributeQuotes: true,
            collapseWhitespace: true,
            removeComments: true,
            collapseBooleanAttributes: true,
            collapseInlineTagWhitespace: true,
            removeRedundantAttributes: true,
            removeScriptTypeAttributes: true,
            removeStyleLinkTypeAttributes: true,
            minifyCSS: true,
            minifyJS: true,
            minifyURLs: true,
            useShortDoctype: true,
          },
    }),
  ],
Copy the code
  • Define variables in constants.js, introduce variables in webpack.dev.js and configure devServer
DevServer: {host: SERVER_HOST, // specify host, default is localhost port: SERVER_PORT, // specify port, default is 8080 compress: Open: true, // Open the default browser hot: true, // hot update},Copy the code
  • NPM run start (NPM run start, NPM run start, NPM run start)
  • Use the clean-webpack-plugin to pack and compile the DIST folder every time the NPM run build is compiled
    • Install command
      npm install clean-webpack-plugin -D
    Copy the code
    • Add the following code to webpack.pord.js to automatically find the path in output and clean it up
       plugins: [
        new CleanWebpackPlugin(),
      ],
    Copy the code
Loader file processing
  • Install style-loader and CSS-loader to perform CSS style processing

    • Install command
      npm install style-loader css-loader -D
    Copy the code
    • Add the following code to webpack.common.js
    module: { rules: [ { test: /\.css$/, use: [ 'style-loader', { loader: 'css-loader', options: { modules: False, // The default value is false. SourceMap: isDev, // The value is the same as devtool. 0, // Specify the laoder number used before CSS loader processing},},],},],},Copy the code
  • Install less and less-loader and process less files

    • Install command
      npm install less less-loader -D
    Copy the code
    • Webpack.common.js rules add code
    { test: /\.less$/, use: [ 'style-loader', { loader: 'css-loader', options: { modules: false, sourceMap: IsDev, importLoaders: 1, // needs to be processed by less-loader first, so set it to 1},}, {loader: 'less-loader', options: {sourceMap: isDev, }, }, ], },Copy the code
  • Install Node-sass and Sass-Loader to process SCSS files

    • Install command
        npm install node-sass sass-loader -D
      Copy the code
    • Add the following code to webpack.common.js rules
      { test: /\.scss$/, use: [ 'style-loader', { loader: 'css-loader', options: { modules: false, sourceMap: IsDev, importLoaders: 1, // Must be processed by ass-loader first, so set it to 1},}, {loader: 'ass-loader', options: {sourceMap: isDev, }, }, ], },Copy the code
  • File-loader or url-loader processes local resource files

    • Install command
      npm install file-loader url-loader -D
    Copy the code
    • Add code to rules
      {
         test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
         use: [
           {
             loader: 'url-loader',
             options: {
               limit: 10 * 1024,
               name: '[name].[contenthash:8].[ext]',
               outputPath: 'assets/images',
             },
           },
         ],
       },
       {
         test: /\.(ttf|woff|woff2|eot|otf)$/,
         use: [
           {
             loader: 'url-loader',
             options: {
               name: '[name].[contenthash:8].[ext]',
              outputPath: 'assets/fonts',
            },
          },
        ],
      },
    Copy the code

React and typescript are supported

React Installation commands
  npm install react react-dom -S
Copy the code
Install babel-loader to identify syntax, otherwise error
  • Install command
      npm install babel-loader @babel/core @babel/preset-react -D
    Copy the code
  • Supports ts installation commands
  npm install @babel/preset-typescript -D
Copy the code
  • The root directory creates a new.babelrc file

      {
        "presets": ["@babel/preset-react", "@babel/preset-typescript"]
      }
    Copy the code
  • Add the following code to the rules of webpack.common.js

{ test: /\.(tsx? |js)$/, loader: 'babel-loader', options: { cacheDirectory: true }, exclude: /node_modules/, },Copy the code
  • If the resolve attribute is added to webpack.common.js, webpack will try to add the.tsx suffix first. If the file cannot be found, it will try to find the file in turn
  resolve: {
    extensions: ['.tsx', '.ts', '.js', '.json'],
  },
Copy the code
  • React type declaration, install command
  npm install @types/react @types/react-dom -D
Copy the code
  • Note that there may be an ESLint error, just change the corresponding value in the ESLint configuration file, then you can try the code in the TSX file and start NPM run start
The tsconfig.json file is created in the root directory
  • Generate file command, also can create their own
      npx tsc --init
    Copy the code
  • Delete the useless code and add the following code
    For details, see GithupCopy the code
    • Talk about baseUrl and Paths, which configure paths and prevent deep nesting
    "BaseUrl" : ". / ", "paths" : / / root directory {/ / path map, associated with baseUrl "Src / *" : / Src / * ", "Components / *" : ["src/components/*"], "Utils/*": ["src/utils/*"] },Copy the code
    • Add the code to webpack.common.js
      resolve: {
        extensions: ['.tsx', '.ts', '.js', '.json'],
        alias: {
          'Src': resolve(PROJECT_PATH, './src'),
          'Components': resolve(PROJECT_PATH, './src/components'),
          'Utils': resolve(PROJECT_PATH, './src/utils'),
        }
      },
    Copy the code
    • Src/Components: Src/Components: Src/Components /.. / the
Babel configuration
  • Part of Babel has already been configured

  • @babel/preset-env Find out the plugin needed to translate ES6+ syntax according to the target browser environment set

    • Install command
      npm install @babel/preset-env -D
    Copy the code
  • Babel/plugin-transform-Runtime resolves some new features, such as includes

    • Install command

        npm install @babel/plugin-transform-runtime -D
        npm install @babel/runtime-corejs3 -S
      Copy the code
    • The @babel/plugin-transform-runtime function is to translate the code. The translated code may introduce modules from @babel/ Runtime-corejs3. So the former runs at compile time and the latter at run time. Similar to Polyfill, the latter needs to be packaged into the final product to run in the browser

  • Modify the code in.babelre

{"presets": [["@babel/preset-env", {// Prevent Babel from projecting any module type to CommonJS, causing tree-shaking invalid problem "modules": false } ], "@babel/preset-react", "@babel/preset-typescript" ], "plungins": [ [ "@babel/plugin-transform-runtime", { "corejs": { "version": 3, "proposals": true }, "useESModules": true } ] ] }Copy the code

Webpack optimization

Note that the official scaffolding public has the favicon.ico file, which we can also introduce in index.html
  • To generate images in the dist folder during NPM run builds, install the copy-webpack-plugin
    • Install command
        npm install copy-webpack-plugin -D
      Copy the code
    • Add the plugin code in webpack.common.js
        new CopyWebpackPlugin({
          patterns: [
            {
              context: resolve(PROJECT_PATH, './public'),
              from: '*',
              to: resolve(PROJECT_PATH, './dist'),
              toType: 'dir',
              globOptions: {
                dot: true,
                gitignore: true,
                ignore: ['**/index.html'],
              },
            },
          ],
        }),
      Copy the code
    • This plugin deals with static resources, as well as other static resources
Display the build progress when starting or building
  • Install the webpackbar command
      npm install webpackbar -D
    Copy the code
  • Add the following code to webpack.common.js, and use whatever color you like
      new WebpackBar({
        name: isDev ? 'run' : 'build',
        color: isDev ? '#00b2a9' : '#ee6139',
      }),
    Copy the code
Typescript type detection at compile time
  • Fork-ts-checker -webpack-plugin prevents unnecessary bugs

    • Install command

        npm install fork-ts-checker-webpack-plugin -D
      Copy the code
    • Add the following code to webpack.common.js

        new ForkTsCheckerWebpackPlugin({
          typescript: {
            configFile: resolve(PROJECT_PATH, './tsconfig.json'),
          },
        }),
      Copy the code
Separate some referenced third-party packages into separate chunks
  • Add the following code to webpack.prod.js
      output: {},
      optimization: {
        splitChunks: {
          chunks: 'all',
          name: false,
          minSize: 0,
        },
      },
    Copy the code
Code hot update
  • After modifying the code, the whole page will not be refreshed, only partial changes to the page

  • Modify the code in webpack.dev.js

    • In the devServerhot: true
    • Add new plugins
        const webpack = require('webpack');
        plugins: [new webpack.HotModuleReplacementPlugin()],
      Copy the code
    • Install @ types/webpack – env
        npm install @types/webpack-env -D
      Copy the code
    • Add the following code to the defined intersection file
        if (module && module.hot) {
          module.hot.accept()
        }
      Copy the code
Remove CSS and package separately and remove unwanted CSS code
  • Mini-css-extract-plugin for CSS style split, packaged separately

    • Install command

        npm install mini-css-extract-plugin -D
      Copy the code
    • Modify the following code in webpack.common.js

      Change 'style-loader' to isDev? 'style-loader' : MiniCssExtractPlugin.loader,Copy the code
    • Add the following code to webpack.prod.js

      const MiniCssExtractPlugin = require('mini-css-extract-plugin'); Add new MiniCssExtractPlugin({filename: 'CSS /[name].[Contenthash :8].css', chunkFilename: 'css/[name].[contenthash:8].css', ignoreOrder: false, }),Copy the code
  • Purgecss-webpack-plugin removes unwanted styles

    • Install command (glob is used to find file paths)
        npm install purgecss-webpack-plugin glob -D
      Copy the code
    • Add the following code to webpack.prod.js
        const PurgeCSSPlugin = require('purgecss-webpack-plugin');
        new PurgeCSSPlugin({
          paths: glob.sync(`${resolve(PROJECT_PATH, './src')}/**/*.{tsx,scss,less,css}`, { nodir: true }),
          whitelist: ['html', 'body'],
        }),
      Copy the code
The compression code
  • Compressed JS code

    • Terser-webpack-plugin install command

        npm install terser-webpack-plugin -D
      Copy the code
    • Add the following code to the optimization of Webpack.prod.js

      ``` const CssMinimizerPlugin = require('css-minimizer-webpack-plugin'); const TerserPlugin = require('terser-webpack-plugin'); Minimize: true, minimizer: [new TerserPlugin({extractComments: false, // Remove all comments except comments with special markers terserOptions: { compress: { pure_funcs: ['console.log']}, // remove console.log},}), new CssMinimizerPlugin(), // Compress CSS code below], ' 'Copy the code
  • Compressed CSS code

    • Css-minimizer-webpack-plugin install command
        npm install css-minimizer-webpack-plugin -D
      Copy the code
    • The code has been added above

The divider

  • I spent a lot of time on this part of the article, and I’m sure there are many shortcomings in the article. I welcome your comments
  • The following will also continue to package and optimize on the basis of this article
  • Githup address:https://github.com/BreezyZhang/react-scaffold