Having translated a history of front-end engineering, Webpack, Babel, Eslint are now pretty much standard features of front-end projects.

However, after work, they rarely contact with these configurations. They write business codes on the basis of previous configurations. Even if you have the opportunity to configure a project from scratch, you will not build these configuration files manually. You can use create-React-app and Ant Design Pro to automatically generate various directories and configuration files, which saves time and effort.

In this article, we manually configure a front-end project from scratch, which involves Webpack, React, Babel, TypeScript, Ant Design, Sass, Eslint, Prettier, and so on. Suitable for step by step operation from zero.

The front-end engineering project is built in node.js environment, and then the NPM packages need to be installed, so the computer must be configured with node environment first.

Create a new directory and execute NPM init to initialize a project.

npm init
Copy the code

Then you can press Enter and just generate the package.json file, which you can change later if you want.

Webpack

ES6 module, CommonJs module, Scss/ LESS, JSX and so on. Through Webpack, we can package, compress and confuse all files, and finally convert them into code recognized by the browser.

In addition to installing Webpack, we need to install the corresponding command line tool webpack-CLI, as well as webpack-dev-server which implements hot loading, that is, automatically listens to our file changes and refreshes the web page.

Since these tools are only used during development, we can install them with the -d (–save-dev) command so that the development environment is not packaged.

npm i -D webpack webpack-cli webpack-dev-server
Copy the code

After installation, package.json will automatically record the installed Node packages, and the corresponding versions are as follows. If the installation is different from mine, some of the later configurations may be slightly different.

{..."devDependencies": {
    "webpack": "^ 5.51.1"."webpack-cli": "^ 4.8.0"."webpack-dev-server": "^ 4.0.0"}}Copy the code

Then create webpack.config.js in the root directory to configure the project, the main configuration entry file, the package export directory, and the devServer directory.

const path = require('path')
module.exports = {
  entry: './src/main.js'.output: {
    path: path.resolve(__dirname, './dist'),
    filename: 'bundle.js'
  },
  devServer: {
    static: path.resolve(__dirname, './dist')}}Copy the code

Create the corresponding file above.

The main. Js file is used to write Hello World on a web page.

// /src/main.js
document.write('hello world')
Copy the code

Dist directory, create an index. HTML file, and add .

<! DOCTYPEhtml>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
    <title>Front-end engineering</title>
  </head>
  <body>
    <div id="app" />
    <script src="bundle.js"></script>
  </body>
</html>
Copy the code

Finally, create two new commands in package.json. The default test command can be deleted.

."scripts": {
    "dev": "webpack-dev-server --mode development --open"."build": "webpack --mode production"},...Copy the code

Run NPM run dev. http://localhost:8080/ is automatically opened.

React

React allows us to focus on building the user interface without having to manually maintain updates to DOM elements and, of course, VUE.

Install the core library React and render the React-DOM for the Web.

npm i react react-dom
Copy the code

Modify SRC /main.js to try it out.

// /src/main.js
import React from 'react';
import ReactDOM from 'react-dom';

class Hello extends React.Component {
    render() {
        return React.createElement('div'.null.`Hello The ${this.props.toWhat}`);
    }
}

ReactDOM.render(
    React.createElement(Hello, { toWhat: 'World by React' }, null),
    document.getElementById('app'));Copy the code

NPM run dev

React provides the JSX syntax to simplify the creation of a complex page.

Let’s rewrite this:

// /src/main.js
import React from 'react';
import ReactDOM from 'react-dom';

class Hello extends React.Component {
  render() {
    return <div>Hello {this.props.toWhat}</div>;
  }
}

ReactDOM.render(
  <Hello toWhat="World by jsx" />.document.getElementById('app'));Copy the code

But then you find that the project is not going to work

And now we need Babel.

Babel

Babel allows us to convert syntax and new functionality into JS that browsers can recognize. Let’s start by installing Babel and the babel-loader used in WebPack.

npm i -D @babel/core babel-loader
Copy the code

Babel-loader is then introduced in webpack to transform JS and change the webpack.config.js file.

const path = require('path')
module.exports = {
  entry: './src/main.js'.output: {
    path: path.resolve(__dirname, './dist'),
    filename: 'bundle.js'
  },
  module: {
    rules: [{test: /\.(js)x? $/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',},},],},devServer: {
    static: path.resolve(__dirname, './dist')}}Copy the code

Then we install @babel/preset- React to convert JSX syntax.

npm i -D @babel/preset-react
Copy the code

Create the Babel configuration file babel.config.json in the root directory.

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

Then run NPM run dev to see the project successfully run!

Then we can install some other Babel to use the latest ES syntax, such as arrow functions, async await, question mark expressions, and so on, and configure whatever we need. When the browser does not support these features, Babel can help us implement Polyfill for demotion.

@babel/preset-env contains many new features of ES, core-js implements Ployfill, all latest features of ES can be trusted to use through these two Babel, if not, we can configure Babel plug-ins separately.

npm i -D @babel/preset-env core-js
Copy the code

Then we can modify the Babel configuration file.

// babel.config.json
{
    "presets": [["@babel/preset-env",
            {
                "useBuiltIns": "usage"."corejs": 3}]."@babel/preset-react"]."plugins": []}Copy the code

UseBuiltIns “: “Usage” automatically determines whether ployfill is imported into each file. Corejs: 3 is the specified version.

TypeScript

More and more projects are introducing TypeScript, especially large ones. Ts allows bugs to be exposed in advance. If you are developing your own, you can also introduce TS to learn about TypeScript in advance.

There are two ways to introduce TS in a project:

  1. useTypeScript Compiler (TSC)tsCompiled intoES5So it can run in a browser. And the use ofTSCPerform type checking.
  2. useBabeltranslationTS, the use ofTSCPerform type checking.

Use the second approach here, and let Babel and TSC do their jobs.

Install TypeScript and React Type first.

npm i -D typescript @types/react @types/react-dom
Copy the code

Create tsconfig.json in the root directory to configure ts.

// tsconfig.json
{
    "compilerOptions": {
        "target": "es5"."module": "commonjs"."lib": [
            "dom"]."jsx": "react"."noEmit": true."sourceMap": true./* Strict Type-Checking Options */
        "strict": true."noImplicitAny": true."strictNullChecks": true,},"include": [
        "src"]}Copy the code

“NoEmit “: true, ts only does type checking and does not compile output.

Then we change SRC /main.js to SRC /main.tsx and add the type.

// /src/main.js
import * as React from 'react';
import * as ReactDOM from 'react-dom';

type Props = {
  toWhat: string;
};
type State = {
 
};

class Hello extends React.Component<Props.State>  {
  render() {
    return <div>Hello {this.props.toWhat}</div>;
  }
}

ReactDOM.render(
  <Hello toWhat="World by jsx" />.document.getElementById('app'));Copy the code

Next configure Babel and install @babel/preset-typescript to change our code from TS to JS.

npm i -D @babel/preset-typescript
Copy the code

Add to Babel configuration file.

// babel.config.json
{
    "presets": [
        "@babel/preset-typescript"["@babel/preset-env",
            {
                "useBuiltIns": "usage"."corejs": 3}]."@babel/preset-react"]."plugins": []}Copy the code

Finally, add TSX to the path Babel matches in webpack.config.js.

const path = require('path')
module.exports = {
  entry: './src/main.tsx'.output: {
    path: path.resolve(__dirname, './dist'),
    filename: 'bundle.js'
  },
  module: {
    rules: [{test: /\.(js|ts)x? $/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',},},],},resolve: {
    // You can omit these suffixes when importing modules
    extensions: ['.tsx'.'.ts'.'.jsx'.'.js'],},devServer: {
    static: path.resolve(__dirname, './dist')}}Copy the code

We can install typescript globally so that we can use the TSC command for type checking.

npm install -g typescript
Copy the code

You can run tSC-w to check the type in real time.

Ant Design

Component libraries are introduced for faster development.

npm install antd
Copy the code

By the way, you can pull out the Hello component from main. TSX and name it App.tsx as usual.

// /src/App.tsx
import * as React from 'react';
import { DatePicker } from 'antd';

type Props = {
    toWhat: string;
};
type State = {

};

class App extends React.Component<Props.State>  {
    render(): JSX.Element {
        return <div>
            Hello {this.props.toWhat}
            <div>
                <DatePicker></DatePicker>
            </div>
        </div>; }}export default App;
Copy the code

We then introduce the ANTD CSS file in main. TSX.

// /src/main.tsx
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import 'antd/dist/antd.css';
import App from './App'

ReactDOM.render(
  <App toWhat="World by jsx" />.document.getElementById('app'));Copy the code

In this case, you need to add the LOADER of CSS to the webpack.config.js configuration file and install it first.

npm i -D style-loader css-loader
Copy the code

Cs-loader allows us to import CSS in JS. Style-loader helps us to insert CSS as style tags into the page.

Configure the Loader after the installation.

const path = require('path')
module.exports = {
  entry: './src/main.tsx'.output: {
    path: path.resolve(__dirname, './dist'),
    filename: 'bundle.js'
  },
  module: {
    rules: [{test: /\.(js|ts)x? $/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',}}, {test: /\.css$/i,
        use: ["style-loader"."css-loader"],},],},resolve: {
    // You can omit these suffixes when importing modules
    extensions: ['.tsx'.'.ts'.'.jsx'.'.js'],},devServer: {
    static: path.resolve(__dirname, './dist')}}Copy the code

Then you successfully introduce the date picker.

Sass

Sass is the precompiler of CSS, which can make writing styles more convenient. The specific features can be referred to the official website. The most I use is to write CSS in nested form, which is very convenient.

Let’s install Sass and its loader.

npm install sass-loader sass  --save-dev
Copy the code

Then configure it in webpack.config.js

const path = require('path');
module.exports = {
  entry: './src/main.tsx'.output: {
    path: path.resolve(__dirname, './dist'),
    filename: 'bundle.js',},module: {
    rules: [{test: /\.(js|ts)x? $/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',}}, {test: /\.css$/i,
        use: ['style-loader'.'css-loader'],}, {test: /\.s[ac]ss$/i,
        use: [
          // Generate JS strings as style nodes
          'style-loader'.// Convert CSS to CommonJS modules
          'css-loader'.// Compile Sass to CSS
          'sass-loader',],},],},resolve: {
    // You can omit these suffixes when importing modules
    extensions: ['.tsx'.'.ts'.'.jsx'.'.js'],},devServer: {
    static: path.resolve(__dirname, './dist'),}};Copy the code

Add a few class names to app.jsx and introduce app.scss.

// /src/App.tsx
import * as React from 'react';
import { DatePicker } from 'antd';
import './App.scss';

type Props = {
  toWhat: string;
};
type State = {};

class App extends React.Component<Props.State> {
  render(): JSX.Element {
    return (
      <div className="app">
        <div className="text">Hello</div>
        <div>{this.props.toWhat}</div>
        <div>
          <DatePicker></DatePicker>
        </div>
      </div>); }}export default App;
Copy the code

Create app. SCSS and add color to experiment.

.app {
  .text {
    color: #f00; }}Copy the code

NPM run dev to see the effect

Eslint

Eslint can be configured to check syntactically statically, as well as ts.

npm i eslint -D
Copy the code

The NPM i-g NPX command can be installed globally to run commands in the node_modules/. Bin directory.

/node_modules/. Bin /eslint –version./node_modules/. Bin /eslint –version Or, like above, typescript is installed globally to execute TSC. Or add a custom command to package.json. But NPX is the most convenient.

Let’s initialize ESLint.

npx eslint --init
Copy the code

Then select the appropriate options according to the project needs, and finally automatically install the corresponding dependencies.

Eslint then automatically generates.eslintrc.js for us and adds “node”: true otherwise module.exports will return an error.

module.exports = {
    "env": {
        "browser": true."es2021": true."node": true,},"extends": [
        "eslint:recommended"."plugin:react/recommended"."plugin:@typescript-eslint/recommended"]."parser": "@typescript-eslint/parser"."parserOptions": {
        "ecmaFeatures": {
            "jsx": true
        },
        "ecmaVersion": 12."sourceType": "module"
    },
    "plugins": [
        "react"."@typescript-eslint"]."rules": {}};Copy the code

We can then add a lint command to package.json to fix the code.

{
  "name": "fe-learn"."version": "1.0.0"."description": "Front-end engineering Project Learning"."main": "index.js"."scripts": {
    "dev": "webpack-dev-server --mode development --open"."build": "webpack --mode production"."lint": "eslint src --fix"
  },
  "author": "windliang"."license": "ISC"."devDependencies": {
    "@babel/core": "^ 7.15.0"."@babel/preset-env": "^ 7.15.0"."@babel/preset-react": "^ 7.14.5"."@babel/preset-typescript": "^ 7.15.0"."@types/react": "^ 17.0.19"."@types/react-dom": "^ 17.0.9"."@typescript-eslint/eslint-plugin": "^ 4.29.2"."@typescript-eslint/parser": "^ 4.29.2"."babel-loader": "^ 8.2.2"."core-js": "^ 3.16.2"."eslint": "^ 7.32.0"."eslint-plugin-react": "^ 7.24.0"."typescript": "^ 4.3.5." "."webpack": "^ 5.51.1"."webpack-cli": "^ 4.8.0"."webpack-dev-server": "^ 4.0.0"
  },
  "dependencies": {
    "react": "^ 17.0.2"."react-dom": "^ 17.0.2"}}Copy the code

Eslint fixes can then be made by executing NPM run Lint.

With Vscode we can also automatically detect eslint while writing code and fix eslint-related errors when saving.

You can install the Eslint plugin and add the following configuration to vscode Settings by clicking on the upper right corner of the image below to edit the configuration directly.

{
  "eslint.validate": ["javascript"."javascriptreact"."vue"."typescript"."typescriptreact"]."editor.codeActionsOnSave": {
    "source.fixAll.eslint": true}},Copy the code

In order to use a more complete ESLint configuration, we can also directly refer to the recommended configuration from Tencent Alloy team, please refer to here.

Prettier

Prettier does code style checks, double or single string quotes How many Spaces? Something like that.

Of course, ESLint can also configure these, but to separate their respective responsibilities, it’s best to format code style using Prettier, install it first.

npm i -D prettier  
Copy the code

Then create a configuration file.prettierrc.js, which directly refers to the configuration recommended by The Alloy team of Tencent.

// .prettierrc.js
module.exports = {
  // max 120 characters per line
  printWidth: 120.// use 2 spaces for indentation
  tabWidth: 2.// use spaces instead of indentations
  useTabs: false.// semicolon at the end of the line
  semi: true.// use single quotes
  singleQuote: true.// object's key is quoted only when necessary
  quoteProps: 'as-needed'.// use double quotes instead of single quotes in jsx
  jsxSingleQuote: false.// no comma at the end
  trailingComma: 'all'.// spaces are required at the beginning and end of the braces
  bracketSpacing: true.// end tag of jsx need to wrap
  jsxBracketSameLine: false.// brackets are required for arrow function parameter, even when there is only one parameter
  arrowParens: 'always'.// format the entire contents of the file
  rangeStart: 0.rangeEnd: Infinity.// no need to write the beginning @prettier of the file
  requirePragma: false.// No need to automatically insert @prettier at the beginning of the file
  insertPragma: false.// use default break criteria
  proseWrap: 'preserve'.// decide whether to break the html according to the display style
  htmlWhitespaceSensitivity: 'css'.// vue files script and style tags indentation
  vueIndentScriptAndStyle: false.// lf for newline
  endOfLine: 'lf'.// formats quoted code embedded
  embeddedLanguageFormatting: 'auto'};Copy the code

Likewise, installing the Prettier plug-in for Vscode and modifying the configuration of Vscode to format it automatically when saving it.

{
  "files.eol": "\n"."editor.tabSize": 2."editor.formatOnSave": true."editor.defaultFormatter": "esbenp.prettier-vscode"."eslint.validate": ["javascript"."javascriptreact"."vue"."typescript"."typescriptreact"]."editor.codeActionsOnSave": {
    "source.fixAll.eslint": true}}Copy the code

conclusion

Through the above series of operations, you can begin to write projects happily, experience is limited, there are problems above, please point out.

The above code is quite piecemeal, you can see the whole code on Github.

Each piece above is a big place, I will continue to learn and summarize in the future, welcome to communicate with you.