1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        從 0 搭建 React 開發(fā)環(huán)境

        共 36359字,需瀏覽 73分鐘

         ·

        2021-02-24 14:46

        作者:發(fā)聲的沉默者| 來源:作者投稿

        https://juejin.cn/post/6929496472232656909

        前言

        為什么要自己造輪子?起初是因為自己并不滿意市面上的腳手架。另外,造輪子對于自己也有一些技術(shù)上的幫助,學(xué)別人二次封裝的東西,不如直接使用底層的庫,這樣也有助于自己系統(tǒng)的學(xué)習(xí)一遍知識,廢話不多說,直接進入正文,如何搭建自己的開發(fā)環(huán)境。

        初始化

        創(chuàng)建文件夾并進入:

        $ mkdir tristana && cd tristana

        初始化 package.json

        $ npm init

        安裝 Webpack

        $ npm install webpack webpack-cli --save-dev

        創(chuàng)建以下目錄結(jié)構(gòu)、文件和內(nèi)容:

        project

        tristana
        |- package.json
        |- /dist
           |- index.html
        |- /script
           |- webpack.config.js
        |- index.html
        |- /src
           |- index.js

        src/index.js

        document.getElementById("root").append("React");

        index.html && dist/index.html



            
                 "utf-8" />
                 tristana
            
            
                 "../src/index.js">
                 "root">

            

        script/webpack.config.js

        module.exports = {
            mode: "development",
            entry: "./src/index.js",
        };

        package.json

        {
            // ...
            "scripts": {
                "build""webpack --mode=development --config script/webpack.config.js"
            },
        }

        然后根目錄終端輸入:npm run build

        在瀏覽器中打開 dist 目錄下的 index.html,如果一切正常,你應(yīng)該能看到以下文本:'React'

        index.html 目前放在 dist 目錄下,但它是手動創(chuàng)建的,下面會教你如何生成 index.html 而非手動編輯它。

        Webpack 核心功能

        Babel

        $ npm install @babel/cli @babel/core babel-loader @babel/preset-env --save-dev

        script/webpack.config.js

        module.exports = {
            // ...
            module: {
                rules: [
                    {
                        test: /\.(js|jsx)$/,
                        loader: "babel-loader",
                        exclude: /node_modules/,
                    },
                ],
            },
        };

        .babelrc

        在根目錄下添加 .babelrc 文件:

        {
            "presets": ["@babel/preset-env""@babel/preset-react"]
        }

        樣式

        $ npm install style-loader css-loader less less-loader --save-dev

        script/webpack.config.js

        module.exports = {
            // ...
            module: {
                rules: [
                    {
                        test: /\.(css|less)$/,
                        use: [
                            {
                                loader: "style-loader",
                            },
                            {
                                loader: "css-loader",
                                options: {
                                    importLoaders: 1,
                                },
                            },
                            {
                                loader: "less-loader",
                                lessOptions: {
                                    javascriptEnabled: true,
                                },
                            },
                        ],
                    },
                ],
            },
        };

        圖片字體

        $ npm install file-loader --save-dev

        script/webpack.config.js

        module.exports = {
            // ...
            module: {
                rules: [
                    {
                        test: /\.(png|svg|jpg|gif|jpeg)$/,
                        loader: 'file-loader'
                    },
                    {
                        test: /\.(woff|woff2|eot|ttf|otf)$/,
                        loader: 'file-loader'
                    }
                ],
            },
        };

        HTML

        $ npm install html-webpack-plugin --save-dev

        script/webpack.config.js

        const HtmlWebpackPlugin = require('html-webpack-plugin');
        module.exports = {
            // ...
            plugins: {
                html: new HtmlWebpackPlugin({
                    title: 'tristana',
                    template: 'public/index.html'
                }),
            }
        };

        index.html



            
                 "utf-8" />
                 tristana
            
            
                 "root">

            

        開發(fā)服務(wù)

        $ npm install webpack-dev-server --save-dev

        script/webpack.config.js

        const path = require("path");
        const HtmlWebpackPlugin = require('html-webpack-plugin');
        module.exports = {
            // ...
            devServer: {
                contentBase: path.resolve(__dirname, "dist"),
                hot: true,
                historyApiFallback: true,
                compress: true,
            },
        };

        package.json

        {
            // ...
            "scripts": {
                "start""webpack serve --mode=development --config script/webpack.config.js"
            },
            // ...
        }

        清理 dist

        $ npm install clean-webpack-plugin --save-dev

        script/webpack.config.js

        const { CleanWebpackPlugin } = require('clean-webpack-plugin');
        module.exports = {
            // ...
            plugins: {
                new CleanWebpackPlugin()
            }
        };

        Tips

        由于 webpack 使用的是^5.21.2 版本,在使用該插件時,會提示clean-webpack-plugin: options.output.path not defined. Plugin disabled...,暫時還未解決。

        環(huán)境變量

        $ npm install cross-env --save-dev

        package.json

        {
            // ...
            "scripts": {
                "start""cross-env ENV_LWD=development webpack serve  --mode=development --config script/webpack.config.js",
                "build""cross-env ENV_LWD=production webpack --mode=production --config script/webpack.config.js"
            },
            // ...
        }

        .jsx 文件

        安裝依賴

        $ npm install @babel/preset-react react react-dom --save-dev

        .babelrc

        {
          "presets": ["@babel/preset-env""@babel/preset-react"]
        }

        src/App.jsx

        在 src 目錄下,新增 App.jsx 文件:

        import React, { Component } from "react";

        class App extends Component {
            render() {
                return (
                    

                        

         Hello, World! 


                    

                );
            }
        }

        export default App;

        src/index.js

        import React from "react";
        import ReactDOM from "react-dom";
        import App from "./App.jsx";
        ReactDOM.render( , document.getElementById("root"));

        React Router

        安裝依賴

        $ npm install react-router history --save

        src/index.js

        import React from "react";
        import ReactDOM from "react-dom";
        import { Router, Route, Link } from "react-router";
        import { createBrowserHistory } from "history";
        import App from "./App.jsx";

        const About = () => {
            return <>About;
        };

        ReactDOM.render(
             history={createBrowserHistory()}>
                 "/" component={App} />
                 "/about" component={About} />
            ,
            document.getElementById( "root")
        );

        MobX

        安裝依賴

        $ npm install mobx mobx-react babel-preset-mobx --save

        .babelrc

        {
          "presets": ["@babel/preset-env""@babel/preset-react""mobx"]
        }

        src/store.js

        在 src 目錄下新建 store.js

        import { observable, action, makeObservable } from "mobx";

        class Store {

            constructor() {
                makeObservable(this);
            }

            @observable
            count = 0;

            @action("add")
            add = () => {
                this.count = this.count + 1;
            };

            @action("reduce")
            reduce = () => {
                this.count = this.count - 1;
            };
        }
        export default new Store();

        index.js

        import { Provider } from "mobx-react";
        import Store from "./store";
        // ...
        ReactDOM.render(
            
                 history={createBrowserHistory()}>
                 "/" component={App} />
                 "/about" component={About} />
                
            ,
            document.getElementById( "root")
        );

        src/App.jsx

        import React, { Component } from "react";
        import { observer, inject } from "mobx-react";

        @inject("store")
        @observer
        class App extends Component {
            render() {
                return (
                    

                        
        {this.props.store.count}

                         add
                         reduce
                    

                );
            }
        }

        export default App;

        Ant Design

        安裝依賴

        $ npm install antd babel-plugin-import --save

        .babelrc

        {
            // ...
            "plugins": [
                [
                    "import",
                    {
                        "libraryName""antd",
                        "libraryDirectory""es",
                        "style"true
                    }
                ]
            ]
        }

        src/App.jsx

        // ...
        import { DatePicker } from "antd";
        import "antd/dist/antd.css";

        @inject("store")
        @observer
        class App extends Component {
            render() {
                return (
                    

                        
                    

                );
            }
        }

        export default App;

        TypeScript

        安裝依賴

        $ npm install typescript @babel/preset-typescript --save-dev

        .babelrc

        {
            "presets": [
                // ...
                "@babel/preset-typescript"
            ]
        }

        tsconfig.json

        在根目錄下,新增 tsconfig.json 文件:

        {
            "compilerOptions": {
                "emitDecoratorMetadata"true,
                "experimentalDecorators"true,
                "target""ES5",
                "allowSyntheticDefaultImports"true,
                "strict"true,
                "forceConsistentCasingInFileNames"true,
                "allowJs"true,
                "outDir""./dist/",
                "esModuleInterop"true,
                "noImplicitAny"false,
                "sourceMap"true,
                "module""esnext",
                "moduleResolution""node",
                "isolatedModules"true,
                "importHelpers"true,
                "lib": ["esnext""dom""dom.iterable"],
                "skipLibCheck"true,
                "jsx""react",
                "typeRoots": ["node""node_modules/@types"],
                "rootDirs": ["./src"],
                "baseUrl""./src"
            },
            "include": ["./src/**/*"],
            "exclude": ["node_modules"]
        }

        src/App.jsx

        更換文件后綴 App.jsx -> App.tsx

        import React, { Component } from "react";
        import { observer, inject } from "mobx-react";
        import { DatePicker } from "antd";
        import "antd/dist/antd.css";

        @inject("store")
        @observer
        class App extends Component {
            props: any;
            render() {
                return (
                    

                        
                        
        {this.props.store.count}

                         add
                         reduce
                    

                );
            }
        }

        export default App;

        代碼規(guī)范

        代碼校驗、代碼格式化、Git 提交前校驗、Vscode配置、編譯校驗。微信搜索公眾號 逆鋒起筆,關(guān)注后回復(fù) 編程資源,領(lǐng)取各種經(jīng)典學(xué)習(xí)資料。

        ESLint

        安裝依賴

        $ npm install @typescript-eslint/parser eslint eslint-plugin-standard @typescript-eslint/parser @typescript-eslint/eslint-plugin eslint-plugin-promise  --save-dev

        .eslintrc.js

        在根目錄下,新增 .eslintrc.js 文件:

        module.exports = {
            extends: ["eslint:recommended""plugin:react/recommended"],
            env: {
                browser: true,
                commonjs: true,
                es6: true,
            },
            globals: {
                $: true,
                process: true,
                __dirname: true,
            },
            parser: "@typescript-eslint/parser",
            parserOptions: {
                ecmaFeatures: {
                    jsx: true,
                    modules: true,
                },
                sourceType: "module",
                ecmaVersion: 6,
            },
            plugins: ["react""standard""promise""@typescript-eslint"],
            settings: {
                "import/ignore": ["node_modules"],
                react: {
                    version: "latest",
                },
            },
            rules: {
                quotes: [2, "single"],
                "no-console": 0,
                "no-debugger": 1,
                "no-var": 1,
                semi: ["error""always"],
                "no-irregular-whitespace": 0,
                "no-trailing-spaces": 1,
                "eol-last": 0,
                "no-unused-vars": [
                1,
                {
                    vars: "all",
                    args: "after-used",
                },
                ],
                "no-case-declarations": 0,
                "no-underscore-dangle": 0,
                "no-alert": 2,
                "no-lone-blocks": 0,
                "no-class-assign": 2,
                "no-cond-assign": 2,
                "no-const-assign": 2,
                "no-delete-var": 2,
                "no-dupe-keys": 2,
                "use-isnan": 2,
                "no-duplicate-case": 2,
                "no-dupe-args": 2,
                "no-empty": 2,
                "no-func-assign": 2,
                "no-invalid-this": 0,
                "no-redeclare": 2,
                "no-spaced-func": 2,
                "no-this-before-super": 0,
                "no-undef": 2,
                "no-return-assign": 0,
                "no-script-url": 2,
                "no-use-before-define": 2,
                "no-extra-boolean-cast": 0,
                "no-unreachable": 1,
                "comma-dangle": 2,
                "no-mixed-spaces-and-tabs": 2,
                "prefer-arrow-callback": 0,
                "arrow-parens": 0,
                "arrow-spacing": 0,
                camelcase: 0,
                "jsx-quotes": [1, "prefer-double"],
                "react/display-name": 0,
                "react/forbid-prop-types": [
                2,
                {
                    forbid: ["any"],
                },
                ],
                "react/jsx-boolean-value": 0,
                "react/jsx-closing-bracket-location": 1,
                "react/jsx-curly-spacing": [
                2,
                {
                    when: "never",
                    children: true,
                },
                ],
                "react/jsx-indent": ["error", 4],
                "react/jsx-key": 2,
                "react/jsx-no-bind": 0,
                "react/jsx-no-duplicate-props": 2,
                "react/jsx-no-literals": 0,
                "react/jsx-no-undef": 1,
                "react/jsx-pascal-case": 0,
                "react/jsx-sort-props": 0,
                "react/jsx-uses-react": 1,
                "react/jsx-uses-vars": 2,
                "react/no-danger": 0,
                "react/no-did-mount-set-state": 0,
                "react/no-did-update-set-state": 0,
                "react/no-direct-mutation-state": 2,
                "react/no-multi-comp": 0,
                "react/no-set-state": 0,
                "react/no-unknown-property": 2,
                "react/prefer-es6-class": 2,
                "react/prop-types": 0,
                "react/react-in-jsx-scope": 2,
                "react/self-closing-comp": 0,
                "react/sort-comp": 0,
                "react/no-array-index-key": 0,
                "react/no-deprecated": 1,
                "react/jsx-equals-spacing": 2,
            },
        };


        .eslintignore

        在根目錄下,新增 .eslintignore 文件:

        src/assets

        .vscode

        在根目錄下新增 .vscode 文件夾,然后新增 .vscode/settings.json

        {
            "eslint.validate": [
                "javascript",
                "javascriptreact",
                "typescript",
                "typescriptreact"
            ]
        }

        Perttier

        安裝依賴

        $ npm install prettier --save-dev

        prettier.config.js

        在根目錄下,新增 prettier.config.js 文件:

        module.exports = {
            // 一行最多 100 字符
            printWidth: 100,
            // 使用 4 個空格縮進
            tabWidth: 4,
            // 不使用縮進符,而使用空格
            useTabs: false,
            // 行尾需要有分號
            semi: true,
            // 使用單引號
            singleQuote: true,
            // 對象的 key 僅在必要時用引號
            quoteProps: 'as-needed',
            // jsx 不使用單引號,而使用雙引號
            jsxSingleQuote: false,
            // 末尾不需要逗號
            trailingComma: 'none',
            // 大括號內(nèi)的首尾需要空格
            bracketSpacing: true,
            // jsx 標簽的反尖括號需要換行
            jsxBracketSameLine: false,
            // 箭頭函數(shù),只有一個參數(shù)的時候,也需要括號
            arrowParens: 'avoid',
            // 每個文件格式化的范圍是文件的全部內(nèi)容
            rangeStart: 0,
            rangeEnd: Infinity,
            // 不需要寫文件開頭的 @prettier
            requirePragma: false,
            // 不需要自動在文件開頭插入 @prettier
            insertPragma: false,
            // 使用默認的折行標準
            proseWrap: 'preserve',
            // 根據(jù)顯示樣式?jīng)Q定 html 要不要折行
            htmlWhitespaceSensitivity: 'css',
            // 換行符使用 lf
            endOfLine: 'lf'
        };

        stylelint

        安裝依賴

        $ npm install stylelint stylelint-config-standard stylelint-config-prettier --save-dev

        stylelint.config.js

        在根目錄下,新增 stylelint.config.js 文件:

        module.exports = {
            extends: ['stylelint-config-standard''stylelint-config-prettier'],
            ignoreFiles: [
                '**/*.ts',
                '**/*.tsx',
                '**/*.png',
                '**/*.jpg',
                '**/*.jpeg',
                '**/*.gif',
                '**/*.mp3',
                '**/*.json'
            ],
            rules: {
                'at-rule-no-unknown': [
                    true,
                    {
                        ignoreAtRules: ['extends''ignores']
                    }
                ],
                indentation: 4,
                'number-leading-zero': null,
                'unit-allowed-list': ['em''rem''s''px''deg''all''vh''%'],
                'no-eol-whitespace': [
                    true,
                    {
                        ignore: 'empty-lines'
                    }
                ],
                'declaration-block-trailing-semicolon''always',
                'selector-pseudo-class-no-unknown': [
                    true,
                    {
                        ignorePseudoClasses: ['global']
                    }
                ],
                'block-closing-brace-newline-after''always',
                'declaration-block-semicolon-newline-after''always',
                'no-descending-specificity': null,
                'selector-list-comma-newline-after''always',
                'selector-pseudo-element-colon-notation''single'
            }
        };

        lint-staged、pre-commit

        安裝依賴

        $ npm install lint-staged prettier eslint pre-commit --save-dev

        package.json

        {
            // ...
            "scripts": {
                "lint:tsx""eslint --ext .tsx src && eslint --ext .ts src",
                "lint:css""stylelint --aei .less .css src",
                "precommit""lint-staged",
                "precommit-msg""echo 'Pre-commit checks...' && exit 0"
            },
            "pre-commit": [
                "precommit",
                "precommit-msg"
            ],
            "lint-staged": {
                "*.{js,jsx,ts,tsx}": [
                    "eslint --fix",
                    "prettier --write",
                    "git add"
                ],
                "*.{css,less}": [
                    "stylelint --fix",
                    "prettier --write",
                    "git add"
                ]
            }
        }

        eslint-webpack-plugin

        安裝依賴

        $ npm install eslint-webpack-plugin --save-dev

        script/webpack.config.js

        const ESLintPlugin = require('eslint-webpack-plugin');
        module.exports = {
            // ...
            plugins: [new ESLintPlugin()],
        };

        總結(jié)

        搭建這個的過程,也是遇到了不少坑,收獲也是蠻多的,希望這個教程能夠幫助更多的同學(xué),少采點坑,完整的 React 開發(fā)環(huán)境可以看這個tristana,求點贊,求關(guān)注!

        我為什么不再用 Vue,而改用 React?
        學(xué)學(xué) React Native 并沒有壞處 | 學(xué)習(xí)資料分享 02
        在應(yīng)用開發(fā)中,我為什么選擇 Flutter 而不是 React Native ?

         
        支持下 
        瀏覽 49
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            中文字幕+乱码+中文乱码电影 | 午夜操逼av | 国产精品自拍偷拍 | 性虎色成人AV | 国产精品久久久久久久专区 | 国产睡熟迷奷一区二区 | 青娱乐99 | 被c视频直接进 | 777色综合 | а中文在线天堂 |