<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

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

          共 14690字,需瀏覽 30分鐘

           ·

          2021-02-19 06:39

          作者:發(fā)聲的沉默者| 來(lái)源:作者投稿
          https://juejin.cn/post/6929496472232656909


          前言

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

          初始化

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

          $?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
          ????
          ????
          ????????
          ????????"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

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

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

          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">

          ????

          開(kāi)發(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?版本,在使用該插件時(shí),會(huì)提示clean-webpack-plugin: options.output.path not defined. Plugin disabled...,暫時(shí)還未解決。

          環(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ī)范

          代碼校驗(yàn)、代碼格式化、Git?提交前校驗(yàn)、Vscode配置、編譯校驗(yàn)

          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?個(gè)空格縮進(jìn)
          ????tabWidth:?4,
          ????//?不使用縮進(jìn)符,而使用空格
          ????useTabs:?false,
          ????//?行尾需要有分號(hào)
          ????semi:?true,
          ????//?使用單引號(hào)
          ????singleQuote:?true,
          ????//?對(duì)象的?key?僅在必要時(shí)用引號(hào)
          ????quoteProps:?'as-needed',
          ????//?jsx?不使用單引號(hào),而使用雙引號(hào)
          ????jsxSingleQuote:?false,
          ????//?末尾不需要逗號(hào)
          ????trailingComma:?'none',
          ????//?大括號(hào)內(nèi)的首尾需要空格
          ????bracketSpacing:?true,
          ????//?jsx?標(biāo)簽的反尖括號(hào)需要換行
          ????jsxBracketSameLine:?false,
          ????//?箭頭函數(shù),只有一個(gè)參數(shù)的時(shí)候,也需要括號(hào)
          ????arrowParens:?'avoid',
          ????//?每個(gè)文件格式化的范圍是文件的全部?jī)?nèi)容
          ????rangeStart:?0,
          ????rangeEnd:?Infinity,
          ????//?不需要寫(xiě)文件開(kāi)頭的?@prettier
          ????requirePragma:?false,
          ????//?不需要自動(dòng)在文件開(kāi)頭插入?@prettier
          ????insertPragma:?false,
          ????//?使用默認(rèn)的折行標(biāo)準(zhǔn)
          ????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é)

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


          瀏覽 36
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  五月丁香婷婷色综合 | 久久国产精品久久久 | 国产精品一区二区在线 | 神马影院午夜福利 | 无码免费一区二区三区免费播放 |