New knowledge storeFront end from entry to groundFor attention, star and suggestions, update from time to time ~

If you think it’s good, please give it a thumbs up

I have been writing the front end for more than a year, but I have not built a project from scratch. Now I start to step on the pit.

The project generally includes the following parts

  • Directory specification
  • react
  • webpack
  • less
  • typescript
  • eslint
  • Axios encapsulation

Initialize the project

First, create a folder called basic-react-app. The name’s not the point. Whatever makes you happy. Then, initialize the project using NPM init and press Enter as prompted

$basic-react-app npm init This utility will walk you through creating a package.json file. It only covers the most common items, and tries to guess sensible defaults. See `npm help json` for definitive documentation on these fields and exactly what they do. Use `npm install <pkg>` afterwards to install a package and save it as a dependency in the package.json file. Package name: (basic-react-app) version: (1.0.0) description: basic react demo entry point: (index.js) test command: git repository: keywords: author: suil license: (ISC) About to write to /Users/zhangpengcheng15/Documents/code/temp/basic-react-app/package.json: { "name": "Basic-react-app ", "version": "1.0.0", "description":" Basic react demo", "main": "index.js", "scripts": {"test": "echo \"Error: no test specified\" && exit 1" }, "author": "suil", "license": "ISC" } Is this OK? (yes)Copy the code

You now have a package.json file

Then, use Git init to initialize the repository, and consider doing it remotely before pulling it locally.

$basic-react-app git init Initialized empty Git repository in / Users/zhangpengcheng15 / Documents/code/temp/basic - the react - app /. Git - react - app / $, basic git ✗ : (master)Copy the code

If you use a special command window or ZSH, you should see git:(master) at the end of your directory, indicating that your local repository is set up.

Don’t worry about the next step, and don’t forget to configure Gitignore, otherwise your computer will get stuck for a while. Create a.gitignore file in the root directory, open it with an editor, and type

node_modules
dist
Copy the code

And save. Ok, now the warehouse initialization is complete.

Directory specification

Finally, open your favorite editor, such as vscode, to create the following file structure.

.
+ |- /src
+   |- /assets
+     |- /less
+     |- /icons
+   |- /components
+   |- /constants
+   |- /static
+     |- /imgs
+   |- /utils 
Copy the code

For those of you who use vscode, you must download vscode- ICONS

Among them,

  • Assets hold resource files, including ICONS of various types, style sheets used globally, and so on
  • Components extract, each folder is a family of components
  • Constants Constant resources, such as extracted configuration constants, common interface definitions, unified placement of request mappings, etc
  • Static Static resources, including multi-language resources, image resources, font resources, and third-party lib resources
  • Utils, the common methods extracted from the project, and so on

Ok, file structure is complete. Install react

React

React is a declarative, efficient, and flexible JavaScript library for building user interfaces. React allows you to combine short, independent pieces of code called “components” into complex UI interfaces.

  • React argues that rendering logic is intrinsically coupled to other UI logic, such as binding events in the UI, notifying the UI when state changes at certain moments, and displaying prepared data in the UI.

  • React does not use artificial separation of markup and logic into separate files. Instead, it separates concerns by storing both together in loosely coupled units called components.

Install React and react-dom from the command line

NPM install react react-dom or yarn add react react-domCopy the code

Before we start, let’s add some files to the directory.

In the SRC directory, create index.tsx and index.less. Don’t worry about whether it will be recognized or run.

// src/index.tsx

import React from 'react';
import ReactDOM from 'react-dom';
import './index.less';  // Be sure to add './' to indicate the current directory

ReactDOM.render(
  <h1>Hello, world!</h1>.document.getElementById('root'));Copy the code
h1{
	color: blue;
}
Copy the code

webpack

What is the webpack

Webpack is a static module wrapper for a modern JavaScript application. When WebPack processes an application, it recursively builds a dependency graph containing each module required by the application, and then packages these modules into one or more bundles.

The core concepts of WebPack

  • Entry: the entrance
  • Output: the output
  • Loader: module converter, used to convert the original content of a module into new content as required
  • Plugins: Extensions that inject extension logic at specific points in the WebPack build process to change the build result or do what you want to do

Install WebPack locally, then install WebPack – CLI (this tool is used to run Webpack on the command line) :

npm install webpack webpack-cli --save-dev
Copy the code

Or yarn add webpack webpack-cli –dev

Current WebPack is based on the latest version

"Webpack" : "^ 4.43.0", "webpack - cli" : "^ 3.3.11." "Copy the code

In WebPack 4, it can be used without any configuration, however most projects will require complex setup, which is why WebPack still supports configuration files.

The purpose of this article is to configure a usable React project, so some of the configuration can be done in one step. For more webPack knowledge, please visit WebPack Chinese

Create a webpack.config.js file in the root directory and write the following

const path = require('path');

module.exports = {
  entry: './src/index.tsx'.mode: "development".devtool: 'cheap-module-eval-source-map'.output: {
    filename: 'bundle.js'.path: path.resolve(__dirname, 'dist')}};Copy the code

If webpack.config.js exists, the webpack command will choose to use it by default. Use the –config option to pass configuration files of any name.

For multi-entry files, you can use the following configuration

entry: { index: './src/index.js', index2: './src/index2.js', }, output: { path: Path. resolve(__dirname,'dist'), // error: filename: '[name].bundle.js',},Copy the code

In the configuration file above, we used the concepts of entry and output. I’m sure you understand what these two configurations mean. We’ll use two other concepts later.

mode

The mode configuration item tells Webpack to use the built-in optimizations for the corresponding mode.

Mode Supports the following two configurations:

  • Development: Set the value of process.env.node_env to development and enable NamedChunksPlugin and NamedModulesPlugin

  • Production: Set process.env.node_env to production, Enable FlagDependencyUsagePlugin FlagIncludedChunksPlugin, ModuleConcatenationPlugin NoEmitOnErrorsPlugin, OccurrenceOrderPlugin SideEffectsFlagPlugin and UglifyJsPlugin

In short, the build goals for * development and production environments are very different. Setting Mode to Development enables some of the webPack default optimizations. Here we’ll set mode: “development”,

devtool

There are some Settings in devtool that help us map the compiled code back to the original source. Different values can significantly affect the speed of builds and rebuilds.

For us, it’s just a matter of being able to locate lines of source code, so given the build speed, devtool is set to cheap-module-eval-source-map in development mode.

For other configuration parameters, see devtool.

Babel

Babel is a JavaScript compiler

The import and export statements in ES2015 have been standardized. Most browsers don’t support them yet, but WebPack provides support right out of the box.

In fact, WebPack works behind the scenes to “translate” code so that older browsers can execute it. Note, however, that WebPack does not change the parts of the code other than the import and export statements. If we need to use other ES2015 features, we need to use an interpreter like Babel or Buble in webPack’s loader system.

Babel is a toolchain for converting ECMAScript 2015+ version code into backwardly compatible JavaScript syntax so it can run in current and older versions of browsers or other environments. Here’s a list of things Babel can do for you:

  • The syntax conversion
  • Polyfill missing features in the target environment (via @babel/ Polyfill module)
  • Source code conversion (Codemods)

Follow the instructions below to install the Babel series

yarn add @babel/core @babel/cli @babel/preset-env @babel/preset-react babel-loader --dev
Copy the code

Among them,

  • @babel/preset-env is an intelligent preset that allows us to use the latest JavaScript without having to manage which syntax needs to be converted (and optional browser padding) in the target environment. This both makes our job easier and makes JavaScript packages smaller!
  • @babel/preset- React converts JSX syntax

One of the best features of WebPack is that you can import any type of file from the Loader in addition to JavaScript. That said, the same JavaScript advantages listed above (such as explicit dependencies) can be used to build all non-javascript content in a Web site or Web application.

Now, in the WebPack configuration object, add babel-loader to the loaders list of the Module, as shown in the current configuration file

module.exports = {
  entry: './src/index.tsx'.mode: "development".devtool: 'cheap-module-eval-source-map'.module: {
    rules: [{test: /\.(js|jsx)$/,
        exclude: /(node_modules|bower_components)/,
        loader: "babel-loader",}]},output: {
    filename: 'bundle.js'.path: path.resolve(__dirname, 'dist')}};Copy the code

Of all the packages I downloaded, this is the one you used? What about those two bags you specifically explained?

Don’t worry, the other packages are used by setting up the Babel configuration file. Create a.babelrc file in the root directory and enter the following content

{
  "presets": [
    "@babel/env"."@babel/preset-react"]}Copy the code

While we’re at it, let’s pay off a debt. Remember the new index.tsx file above? Webpack doesn’t know TSX files, browsers don’t know TSX files, so who does?

Babel, of course. Prior to version 7, we needed a special TS-loader to escape TS and TSX files, but now Babel is all we need

Whether the code has ES2015 features, JSX, TypeScript, or some other crazy custom ———— compiler knows what to do. Say goodbye to TS-Loader, TS-Jest, TS-karma, create-react-app-typescript, etc. Use Babel instead.

yarn add @babel/preset-typescript --dev
Copy the code

Added in the.babelrc file

{
  "presets": [
    "@babel/env"."@babel/preset-react",
+   "@babel/preset-typescript"],}Copy the code

Well, to this, the ts | TSX file can use Babel – loader compiled, remember to modify the webpack. Config. Js file, add ts | TSX use Babel – loader compilation

 rules: [
      {
        test: /\.(js|jsx|ts|tsx)$/,
        exclude: /(node_modules|bower_components)/,
        loader: "babel-loader"],},Copy the code

Loader

For loader usage,

The test field is a matching rule and is processed for files that match the rule.

The use field can be written several ways

  • It can be a string, such as the one aboveuse: 'babel-loader'
  • It can be an array, as in the CSS file below,use: ['style-loader', 'css-loader']
  • useEach item in the array can be either a string or an object, and when we need thewebpackIn the configuration fileloaderTo configure, you need to write it as an object, and in the object’soptionsField, such as abovebabel-loaderAnother form of configuration can be used
rules: [
    {
        test: /\.jsx?$/,
        use: {
            loader: 'babel-loader',
            options: {
                presets: ["@babel/preset-env"]
            }
        },
        exclude: /node_modules/
    }
]
Copy the code

css

Now, go pay another debt, the less file. For WebPack to recognize less files, it’s less loader. Of course, we also added CSS file recognition.

The choice of less and sass, can walk sass. Vs. less | introduction and comparison

To import a CSS file from a JavaScript module, you need to install and add style-loader and CSS-loader in the Module configuration:

yarn add style-loader css-loader less-loader --dev
Copy the code

webpack.config.js

 rules: [
      {
        test: /\.(js|jsx|ts|tsx)$/,
        exclude: /(node_modules|bower_components)/,
        loader: "babel-loader",
      },
+     {
+       test: /\.css$/,
+       use: [
+         'style-loader',
+         'css-loader'
+       ]
+     },
+     {
+     test: /\.less$/,
+       use: [
+         'style-loader',
+         'css-loader',
+         'less-loader'+] +}],Copy the code

Tip: in vscode, select the + sign, then press win + D, you can select the plus sign continuously, and finally press delete to delete all the + signs

postcss-loader

PostCss is a style manipulation tool that redefines CSS through a custom ecosystem of plug-ins and tools. It encourages developers to write code using the canonical CSS native syntax, then configure the compiler conversion to require a compatible browser version, and finally convert the source code by compilation to CSS code available in the target browser.

yarn add postcss-loader autoprefixer --dev
Copy the code

webpack.config.js

 rules: [
     {
       test: /\.css$/,
       use: [
         'style-loader'.'css-loader',
+        'postcss-loader',]}, {test: /\.less$/,
       use: [
         'style-loader'.'css-loader',
+        'postcss-loader'.'less-loader']}],Copy the code

Postcss-loader is designed to prefix browsers, but it can only prefix them because it doesn’t know which one to add and which not to add. So we need Autoprefixer to tell it which to add and which not to add.

Add postcss.config.js in the root directory

module.exports = {
  plugins: [
    require('autoprefixer')
  ]
}
Copy the code

Add the following fields to package.json to determine which step we want to support

  "browserslist": [
    "defaults",
    "not ie < 11",
    "last 2 versions",
    "> 1%"
  ]
Copy the code

Just in case, let’s install the other two loaders we’ll use here

File – loader and url – loader

  • Using file-loader, you can easily mix images, fonts, and more into a packaged file.
  • The url-loader function is similar to file-loader, but returns a DataURL if the file size (in bytes) is below the specified limit.
yarn add url-loader file-loader --dev
Copy the code

Add rules rules to webpack.config.js

 {
   test: /\.(png|svg|jpg|gif)$/,
     use: [
       {
         loader: 'url-loader',
         options: {
           limit: 2048,
         }
       },
       'file-loader',
     ]
 },
{
  test: /\.(woff|woff2|eot|ttf|otf)$/,
  use: [
  	'file-loader'
  ]
},
Copy the code

resolve

Resolve configures how Webpack finds the files for the modules that depend on it, starting from the configured entry module.

resolve.alias

Create an alias for import or require to make module introduction easier. For example, some common modules are located in the SRC/folder:

resolve: {
   alias: {
        '@': path.resolve(__dirname, "src/")
      }
}
Copy the code

In this way, components or functions that reference their own encapsulation can start with @, for example

import BaseButton from "./components/Button/BaseButton";
Copy the code

This way, avoid endless.. /.. /.. /, and in case a component switches directories, external references in the component do not need to be readjust because they always start looking relative to the SRC path.

Note that only webpack recognition is allowed here. To enable path prompt, you need to configure path in tsconfig.json

Plugin

clean-webpack-plugin

Each time the files are modified, the files in the dist directory are repackaged. How to do? Use the clean-webpack-plugin to automatically clean the /dist/ directory every time you build, leave you want to stay, clear you want to clear, one-click configuration, care for the terminal lazy you

yarn add clean-webpack-plugin --dev
Copy the code

webpack.config.js

+ const CleanWebpackPlugin = require('clean-webpack-plugin');

 module.exports = {
   
    plugins: [+new CleanWebpackPlugin({
+           cleanOnceBeforeBuildPatterns:['* * / *'.'! store'.'! store/**'] // do not delete files in the store directory+}),]};Copy the code

Note: this article does not split configuration files for different environments, please comment out this plug-in when debugging locally

For more configuration, go to clean-webpack-plugin

HtmlWebpackPlugin

You might need an HtmlWebpackPlugin, otherwise, you might be wondering, where does the React component render hang? Will it make its own Html template if it can’t find it?

No, I’m just lazy about not creating a template file,

Without the plugin, the [name].bundle.js generated every time webPack was packaged would have to be manually configured, and now it frees up your hands and you can happily do something else.

yarn add html-webpack-plugin --dev
Copy the code

HtmlWebpackPlugin by default generates an index.html file in the output directory, regardless of whether you created it or not, and all bundles are automatically added to the HTML.

+ const HtmlWebpackPlugin = require('html-webpack-plugin'); plugins: [new CleanWebpackPlugin ({cleanOnceBeforeBuildPatterns: [' * * / * ', '! Store ', '! Store / * * '] / / not to delete store files in the directory}). + new HtmlWebpackPlugin({ + title: 'Basic react app' + }) ],Copy the code

Of course, in general, we sometimes need to create a new index.html template file in the public directory that defines some of our custom content, but I still don’t want to use my hands to import the bundle.js file generated by packaging.

New HtmlWebpackPlugin({template: './public/index.html', filename: 'index.html', // package filename config: config.template})Copy the code

HTML – Webpack-plugin for more functions

webpack-dev-server

Having said that, it’s time to meet Hello World. Or I’m afraid you won’t be able to watch it.

Webpack-dev-server provides a simple Web server that can live reloading. Let’s run the following command:

yarn add webpack-dev-server --dev
Copy the code

Modifying a Configuration File

+ devServer: {+ port: '3000', / / default is 8080 + publicPath: "http://localhost:3000/dist/", + hotOnly: true, + contentBase: './dist' + },Copy the code

Add scripts in package.json

  "scripts": {
      "watch": "webpack --watch",
      "start": "webpack-dev-server --open",
      "build": "webpack"
    },
Copy the code

On the CLI, run yarn build and then yarn start. The page is displayed. -> Meet Hello World

Typescript

eslint

Although we use the Babel to compile the ts | TSX composite file, however, sometimes we will miss ts type error check, for example

“No! I’m not going to compile this thing! Your code is abnormal in 42 different files!”

How do I check for type errors? Add a Lint script to invoke the TypeScript compiler. For example, adjust the NPM test command to check first and then continue running the unit test.

Due to performance issues, TypeScript officially adopted ESLint as a full testing platform, even using a Repository, while ESLint’s TypeScript parser became a separate project focused on compatibility issues.

yarn add eslint typescript @typescript-eslint/parser @typescript-eslint/eslint-plugin --dev
Copy the code

Also, we’re a React App project, so, you know

yarn add eslint-plugin-react eslint-plugin-react-hooks --dev
Copy the code

Create the.eslintrc.js file in the root directory and fill in the following contents

module.exports = {
  root: true,
  parser: '@typescript-eslint/parser',
  parserOptions: {
    "ecmaFeatures": {
        "jsx": true
    },
    "ecmaVersion": 11,
    "sourceType": "module",
    project: './tsconfig.json',
},
  plugins: [
    "react",
    "react-hooks",
    '@typescript-eslint',
  ],
  extends: [
    'eslint:recommended',
    'plugin:@typescript-eslint/recommended',
    'plugin:react/recommended',
    'plugin:react-hooks/recommended',
  ],
};
Copy the code

There are always files that don’t need to be checked. People can embarrass others, but don’t embarrass themselves, so create an.eslintignore file in the root directory

Config/scripts/ node_modules/ \.eslintrc.js // kill itself... webpack.config.jsCopy the code

After consideration, add airbnb rules

yarn add eslint-config-airbnb-typescript eslint-plugin-jsx-a11y eslint-plugin-import --dev
Copy the code

Replace the eslintrc.js file with

 extends: [
    'airbnb-typescript',
    'plugin:@typescript-eslint/recommended',
    'plugin:react/recommended',
    'plugin:react-hooks/recommended',
  ],
Copy the code

Don’t forget to download the eslint plugin in vscode

While the above rules have been tested, there are always some that are redundant or missing to us, so we add the rules field to the.eslintrc.js file to enable or disable certain rules

"Rules ": {// disallow var' no-var': "error", // use interface instead of type '@typescript-eslint/consistent-type-definitions': [ "error", "interface" ], '@typescript-eslint/no-explicit-any': 'off', '@typescript-eslint/explicit-module-boundary-types': 'off', "react-hooks/rules-of-hooks": "error", "react-hooks/exhaustive-deps": "warn", "react/prop-types": "off", }Copy the code

Modify script in package.json

 "scripts": {
    "lint": "eslint --ext .ts --ext .tsx src/",
    "watch": "webpack --watch",
    "start": "webpack-dev-server --open",
    "build": "webpack"
  },
Copy the code

Run YARN Lint and have fun fanning yourself…

I left three errors in SRC /index.tsx, roughly? You can try to change the rules

custom.d.ts

How to generate tsconfig.json?

  1. Find a ready-made copy to the root directory, of course, do not copy randomly
  2. Execute if typescript is installed globallytsc --init

  "compilerOptions": {
    "target": "es5",
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "allowJs": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": false,
    "outDir": "./dist/",
    "forceConsistentCasingInFileNames": true,
    "module": "commonjs",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    // "isolatedModules": true,
    // "noEmit": true,
    "jsx": "react",
    "experimentalDecorators": true,
    "baseUrl": ".",
    "paths": {
      "@/*":["src/*"]
    }
  },
  "include": [
    "src","test",
  ]
}
Copy the code

Configuration items are not the focus of this article, but for the purposes of the following. In typscript is unable to identify the source code, so if you are trying to import an SVG | PNG files such as will prompt you always find a module ‘. PNG ‘.

custom.d.ts

declare module "*.svg" {
  const content: any;
  export default content;
}
declare module "*.png" {
  const content: any;
  export default content;
}
Copy the code

Tsconfig. json contains an include field, which represents the content that ts needs to escape. If you put custom.d.ts files in the directory included in the include field, you can solve the problem of not knowing other types.

Finally, I enclose here

  • airbnbRegular portal [airbnb】
  • typescript-eslintRegular portal [typescript-eslint】
  • Article Portal [On how to gracefully write code that Doesn’t Get beat up]

This is the end of this tutorial, this is just a concise tutorial, if there is something wrong, feel free to point it out in the comments and I will fix it

Later, there will be a special compilation for webPack and ESLint syntax specifications

If you learn something new, please give it a thumbs upCopy the code

This article contains: a journey of large front end foundation building from scratch (simple and profound, constantly updated ~)

Recommended reading:

  • In a few words with you to understand the “closure” | add usage scenario is very simple to explain why going?

  • Chaohuaxishi, re-introduction of inheritance and prototype chain has a picture of the truth

  • Reflow and Repaint, KFC and MC are mentioned at the same time every time. The relationship is almost as close as MC beside KFC.

  • The lexical scope and the chain of scope explain that to look at the picture is king

  • Viewport and 1 px | tools: this is a 1 px, designer: no, I can’t, this is not a design but ready to quarrel with me

  • Edible “dry” CSS layout, pure Html example, can debug | horizontal, vertical, multiple columns can watch, adjustable, can be taken away, the only, no branch

  • Front end must master “CSS cascade context” explain | handmade sample, BaoJiao package will sister with cat, what do you want?

Reference documentation

  1. Webpack Chinese website
  2. babel
  3. eslint
  4. typescript