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

          2021年從零開發(fā)前端項目指南

          共 24667字,需瀏覽 50分鐘

           ·

          2021-09-12 00:59


          之前翻譯過一篇 前端工程化發(fā)展歷史 的文章,WebpackBabelEslint 現(xiàn)在基本上就是前端項目的標(biāo)配了。

          但工作以后一般很少接觸這些配置,都是在前人配置好的基礎(chǔ)上去寫業(yè)務(wù)代碼。即使有機(jī)會從零配置一個項目,一般也不會自己手動建這些配置文件,直接用 create-react-appAnt Design Pro 等自動幫我們生成各個目錄和配置文件就可以了,省時省力。

          這篇文章的話就從零手動去配置一個前端項目,會涉及到 WebpackReactBabelTypeScriptAnt DesignSassEslintPrettier,本文的話就本著「不求甚解」的態(tài)度,主要過一下各個模塊的使用,適合從零一步一步跟著操作。

          前端工程化項目是建立在 node.js 環(huán)境下的,之后需要安裝各個 npm 包,所以首先電腦必須已經(jīng)配置好了 node 環(huán)境。

          新建一個目錄然后執(zhí)行 npm init 來初始化一個項目。

          npm init

          然后一路回車就可以,只是生成了 package.json 文件,后續(xù)想改的話也能改。

          img

          Webpack

          前端不斷發(fā)展,但很多特性瀏覽器不一定會支持,ES6 模塊,CommonJs 模塊、Scss/lessjsx 等等,通過 Webpack 我們可以將所有文件進(jìn)行打包、壓縮混淆,最終轉(zhuǎn)換為瀏覽器識別的代碼。

          除了安裝 Webpack ,我們需要安裝對應(yīng)的命令行工具 webpack-cli,以及實現(xiàn)了熱加載,也就是自動監(jiān)聽我們文件變化然后刷新網(wǎng)頁的 webpack-dev-server

          由于這些工具只在開發(fā)階段使用,所以我們安裝的時候可以加上 -D(--save-dev) 命令,這樣開發(fā)環(huán)境就不會打包了。

          npm i -D webpack webpack-cli webpack-dev-server

          安裝之后 package.json 會自動記錄我們安裝的 node 包,對應(yīng)版本如下,如果安裝的和我不一樣的話,后邊的一些配置可能略有不同。

          {
            ...
            "devDependencies": {
              "webpack""^5.51.1",
              "webpack-cli""^4.8.0",
              "webpack-dev-server""^4.0.0"
            }
          }

          接下來在根目錄新建 webpack.config.js 進(jìn)行項目的配置,主要配置入口文件,打包輸目錄,以及 devServer 的目錄。

          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')
            }
          }

          新建一下上邊相應(yīng)的文件。

          main.js 文件主要實現(xiàn)在網(wǎng)頁寫 hello world

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

          新建 dist 目錄,在里邊新建 index.html 文件,引入 <script src="bundle.js"></script>

          <!DOCTYPE html>
          <html>
            <head>
              <meta charset="utf-8">
              <meta name="viewport" content="width=device-width,initial-scale=1.0">
              <title>前端工程化</title>
            </head>
            <body>
              <div id="app" />
              <script src="bundle.js"></script>
            </body>
          </html>

          最后在 package.json 新建兩條命令,默認(rèn)的 test 命令可以直接刪掉了。

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

          執(zhí)行 npm run dev ,此時會自動打開 http://localhost:8080/

          img

          React

          React 可以讓我們專注于構(gòu)建用戶界面,而不需要再手動維護(hù) dom 元素的更新,當(dāng)然還可以用 VUE

          安裝核心庫 react ,以及渲染 Webreact-dom

          npm i react react-dom

          修改 src/main.js 體驗一下。

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

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

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

          npm run dev 看下效果:

          img

          這里會發(fā)現(xiàn)上邊都調(diào)用了 React.createElement 來創(chuàng)建元素,如果頁面復(fù)雜的的話,那一層套一層就太繁瑣了,React 為我們提供了 JSX 語法來簡化寫法。

          讓我們改寫一下:

          // /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')
          );

          但此時會發(fā)現(xiàn)項目跑不起來了

          img

          現(xiàn)在,我們就需要 Babel 了。

          Babel

          babel 可以為我們把各種語法、新功能轉(zhuǎn)換為瀏覽器所能識別的 js 。這里我們先安裝一下 babel 以及在 webpack 中使用的 babel-loader

          npm i -D @babel/core babel-loader

          然后在 webpack 中引入 babel-loader ,用來對 js 進(jìn)行轉(zhuǎn)換,更改 webpack.config.js 文件。

          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')
            }
          }

          然后我們來安裝 @babel/preset-react  來轉(zhuǎn)換 jsx 語法。

          npm i -D @babel/preset-react

          在根目錄新建 babel 的配置文件 babel.config.json

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

          此時再運行 npm run dev  就發(fā)現(xiàn)項目成功跑起來了!

          然后我們還可以安裝一些其他 babel 以便使用最新的 ES 語法,比如箭頭函數(shù)、async await、問號表達(dá)式等等, 需要什么就可以配置什么。當(dāng)瀏覽器不支持這些特性時,babel 可以幫我們實現(xiàn) polyfill 進(jìn)行降級。

          @babel/preset-env 包含了許多 ES 的新特性,core-js 實現(xiàn) ployfill,通過這兩個 babel 各種 ES 最新的特性就都可以放心使用了,如果有不滿足的我們可以單獨配置 babel 的插件。

          npm i -D @babel/preset-env core-js

          然后我們再修改下 babel 的配置文件。

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

          其中 useBuiltIns": "usage" 代表自動判斷每個文件是否引入 ployfillcorejs: 3 是指定版本。

          TypeScript

          越來越多的項目引入了 TypeScript ,尤其是規(guī)模比較大的項目,通過 ts 可以讓一些 bug 提前暴露,平時自己開發(fā)的話也可以引入 ts,提前了解學(xué)習(xí)。

          項目引入 ts 的話有兩種方式:

          1. 使用  TypeScript Compiler (TSC)ts 編譯為 ES5 以便能夠在瀏覽器中運行。并且使用 TSC 進(jìn)行類型檢查。

          2. 使用 Babel 翻譯 TS,使用 TSC 進(jìn)行類型檢查。

          這里的話使用第二種方式,讓 BabelTSC 各司其職。

          首先安裝 TypeScript 以及 React  的 type

          npm i -D typescript @types/react @types/react-dom

          根目錄新建 tsconfig.json 進(jìn)行 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"
              ]
          }

          "noEmit": true, 表明 ts 只做類型檢查,不進(jìn)行編譯輸出。

          然后我們將 src/main.js 修改為 src/main.tsx,并且加上類型。

          // /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')
          );

          接下來進(jìn)行 babel 的配置,安裝 @babel/preset-typescript,將我們代碼從 ts 轉(zhuǎn)為 js

          npm i -D @babel/preset-typescript

          babel 配置文件中加入。

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

          最后在 webpack.config.jsbabel 匹配的路徑中加入 tsx

          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: {
              // 引入模塊的時候可以省略這些后綴
              extensions: ['.tsx''.ts''.jsx''.js'],
            },
            devServer: {
              static: path.resolve(__dirname, './dist')
            }
          }

          我們可以全局安裝一下 typescript ,便于使用 tsc 命令進(jìn)行類型檢查。

          npm install -g typescript

          可以運行一下 tsc -w 實時進(jìn)行類型檢查。

          img

          Ant Design

          引入組件庫,方便更快的開發(fā)。

          npm install antd

          順便可以按照習(xí)慣把 main.tsx 中的 hello 組件抽離出來并且命名為 app.tsx

          // /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;

          然后我們在 main.tsx 引入 antdcss 文件。

          // /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')
          );

          此時就需要在 webpack.config.js 配置文件中補上 cssloader ,先安裝一下。

          npm i -D style-loader css-loader

          css-loader 可以讓我們在 js 中引入 cssstyle-loader 幫我們將 cssstyle 標(biāo)簽的形式插入到頁面。

          安裝好后進(jìn)行配置 loader

          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: {
              // 引入模塊的時候可以省略這些后綴
              extensions: ['.tsx''.ts''.jsx''.js'],
            },
            devServer: {
              static: path.resolve(__dirname, './dist')
            }
          }

          然后就成功引入日期選擇器了。

          img

          Sass

          Sasscss 的預(yù)編譯器,可以讓我們寫樣式更順手,具體特性可以參考 官網(wǎng),我用的最多的就是可以嵌套形式寫 css,很方便。

          我們安裝一下 Sass 以及它的 loader

          npm install sass-loader sass  --save-dev

          然后在 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: [
                    // 將 JS 字符串生成為 style 節(jié)點
                    'style-loader',
                    // 將 CSS 轉(zhuǎn)化成 CommonJS 模塊
                    'css-loader',
                    // 將 Sass 編譯成 CSS
                    'sass-loader',
                  ],
                },
              ],
            },
            resolve: {
              // 引入模塊的時候可以省略這些后綴
              extensions: ['.tsx''.ts''.jsx''.js'],
            },
            devServer: {
              static: path.resolve(__dirname, './dist'),
            },
          };

          App.jsx 加幾個類名,引入 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<PropsState{
            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;

          新建 App.scss,添加顏色實驗一下。

          .app {
            .text {
              color: #f00;
            }
          }

          npm run dev 看下效果

          img

          Eslint

          可以配置 eslint 來進(jìn)行語法上靜態(tài)的檢查,也可以對 ts 進(jìn)行檢查。

          npm i eslint -D

          可以全局安裝一下 npm i -g npx 命令,能夠更方便的運行 node_modules/.bin 目錄下的命令.

          不然的話我們要執(zhí)行 eslint 命令的話需要執(zhí)行 ./node_modules/.bin/eslint --version 才能取到。或者像上邊為了執(zhí)行 tsc 命令,全局安裝了 typescript。或者在 package.json 里邊添加一個自定義命令。不過還是 npx 是最方便的。

          讓我們初始化 eslint.

          npx eslint --init

          然后按照項目需要選擇對應(yīng)的選項,最后自動安裝相應(yīng)的依賴。

          img

          然后 eslint 就自動為我們生成了 .eslintrc.js 配置文件,順便補一個 "node": true,不然的話 module.exports 直接報錯。

          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": {
              }
          };

          然后我們在 package.json 中可以添加一個 lint 命令來修復(fù)代碼。

          {
            "name""fe-learn",
            "version""1.0.0",
            "description""前端工程化項目學(xué)習(xí)",
            "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"
            }
          }

          然后執(zhí)行 npm run lint 即可進(jìn)行 eslint 的相關(guān)修復(fù)。

          配合 Vscode 我們也可以做到邊寫代碼邊自動檢測 eslint,以及保存的時候自動修復(fù) eslint 相關(guān)錯誤。

          可以安裝 Eslint 插件,以及在 vscode 的設(shè)置中加入以下配置,點擊下圖的右上角可以直接進(jìn)行配置的編輯。

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

          為了使用更完善的 eslint 配置,我們也可以直接引用騰訊 Alloy 團(tuán)隊的推薦配置,參考 這里。

          Prettier

          prettier 主要做代碼風(fēng)格上的檢查,字符串雙引號還是單引號?幾個空格?類似這樣的。

          當(dāng)然 eslint 也可以配置這些,但為了分離它們各自的職責(zé),最好還是用 prettier 來格式化代碼風(fēng)格,先安裝一下。

          npm i -D prettier  

          然后新建一個配置文件 .prettierrc.js,這里直接引用 騰訊 Alloy 團(tuán)隊推薦的配置。

          // .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,
            rangeEndInfinity,
            // 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',
          };

          同樣的,為了保存的時候自動幫我們格式化,我們可以安裝 VscodePrettier 插件,以及再修改 Vscode 的配置。

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

          總結(jié)

          通過上邊一系列的操作后,就可以開始愉快的開始寫項目了,經(jīng)驗有限,上邊有問題的地方還請大家指出。

          上邊的代碼都比較零碎,可以在 github 上看整個代碼,后臺回復(fù)「前端配置」即可得到鏈接。

          上邊每一塊都是一個很大的地方,未來的話會繼續(xù)邊學(xué)習(xí)邊總結(jié),歡迎一起交流。


          瀏覽 60
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

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

          手機(jī)掃一掃分享

          分享
          舉報
          <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>
                  亚洲精品无码视频在线观看 | 美女嗦鸡吧视频网站 | 国产一级黄片视频 | 99精品在线 | 亚洲欧美婷婷五月色综合 |