webpack 5 下的 react-typescript

base-react-typescript

前言

本文主要寫於 2021 - 02 - 09 。使用時候須要看 package.json 的版本,避免出錯。
全文主要講述的是,從 0 開始搭建一個屬於本身能夠徹底控制的 react 項目。主要涉及 webpack 邏輯,DLL 生成 等多個方面。後續會補充實際項目中使用等等。git 地址:https://gitee.com/sanyuelanv/...javascript

項目框架

咱們先來簡單的熟識一下整個項目的架構。在後續開發都依靠着這一個架構去拓展。css

├── app // 源碼目錄
│   ├── app.common.css // 全局的 CSS 代碼,只須要一個!
│   ├── app.html  // 模版 HTML
│   ├── app.tsx // 主要入口
│   ├── components // 組件
│   ├── config // 配置文件
│   ├── image // 圖片素材
│   ├── router // 路由
│   ├── typings.d.ts // 全局 type
│   └── utils // 工具函數使用
├── build // 打包後目錄
├── dll // 打包後目錄
├── webpack.config.js // webpack 打包配置
└── webpack.dll.config.js // DLL 打包配置

依賴下載

  • devDependencies - 開發依賴包html

    npm i --save-dev @babel/cli @babel/core @babel/preset-env @babel/preset-react @babel/preset-typescript  @types/react @types/react-dom  @typescript-eslint/eslint-plugin @typescript-eslint/parser autoprefixer babel-loader css-loader eslint eslint-plugin-react eslint-plugin-react-hooks file-loader html-webpack-plugin ip   postcss postcss-loader style-loader typescript url-loader webpack webpack-cli webpack-dev-server clean-webpack-plugin terser-webpack-plugin optimize-css-assets-webpack-plugin mini-css-extract-plugin add-asset-html-webpack-plugin html-webpack-tags-plugin copy-webpack-plugin

    按照完以上長長的開發依賴以後,咱們須要一個個去簡單解析一下對應的做用java

    • @types:@types 開頭的都是爲 typescript 提供 type 內容的。好比你安裝了 react 包,可是 vscode 在 node_modules/react 下 找到不到對的 *.d.ts 文件,就會建議你安裝一個 @types/react 依賴來便於識別。其餘第三方包同理。這裏使用到的是 @types/react @types/react-dom 和 @types/react-dom 兩個基礎的依賴包。隨着項目深刻,咱們會使用到更多的這類依賴包。
    • @babel:@babel 開頭的都是 babel 相關的工具包和插件。主要使用到有:@babel/cli @babel/core @babel/preset-env @babel/preset-react,其中功能做用,咱們能夠在 webpack 配置的一章能夠看到。
    • eslint 相關:eslint, @typescript-eslint/eslint-plugin, @typescript-eslint/parser, eslint-plugin-react-hooks 這些都是 eslint 的相關插件和主要邏輯包,具體做用在 eslint 配置能夠看到。
    • webpack 以及它的助手們:剩餘的咱們均可以在 webpack 配置中看到他們的做用。它們一個個都爲不一樣的文件 js / css / html / image 而來。
  • dependencies - 普通依賴包node

    npm i --save core-js react react-dom  regenerator-runtime whatwg-fetch

    普通依賴包和上面的 devDependencies 不同,它是須要打包進去咱們發佈的 JS 文件中的。所以在後續增長和選擇的時候須要對他們的內容,大小進行分析和了解才加入。避免打包出來的文件過大。react

    • core-js:配合 webpack 能作到針對使用的 API 導入不一樣的補丁包去適配瀏覽器
    • regenerator-runtime:async 函數的補丁包,和 core-js 同樣,配合 webpack 能作到自動導入。
    • whatwg-fetch: fetch 的補丁包,若是你更喜歡 axios 的話,能夠不加這個。

webpack 配置

首先在 package.json 文件中的 scripts 加上對應的命令。這些命令的對應着 開發環境 / 正式環境 / DLL 的打包。這一節是講述 開發環境 / 正式環境 的打包。主要都是在 webpack.config.js 這個文件中操做。webpack

"scripts": {
  "dev": "webpack serve --env NODE_ENV=dev",
  "production": "webpack --env NODE_ENV=production --profile --json > stats.json",
  "dll": "webpack --config webpack.dll.config.js"
},

不少講 webpack 的文章都喜歡把 webpack.config.js 分開成兩個文件,再使用一些合併函數來合併通用的,而我這裏更加偏向在一個文件中操做,根據 dev / production 命令中設置的 NODE_ENV 的不一樣去返回對應的 webpack 配置(webpack.config.js 的本質即便須要導出(module.exports)一個能 返回 webpack config json 的函數)。 ios

webpack.config.js 中的內容不少,可是首先把它分紅兩部分。module.exports 以前的 和 module.exports 以後的。git

  • module.exports 以後的web

    • module - 模塊

      在 webpack 眼中,項目內的全部文件都是 模塊(module)。而在 webpack 的 module 字段中咱們須要作的就是制定規則(rules)。這個 rules 的主要做用是描述不一樣文件該由誰去解析(不一樣的loader)。

      因此在整個 webpack.config.js 文件中你能看到不少的 xxLoaderxxxRule 對象。不一樣的 Loader 在 Rule 的 use 中進行組裝。而 rule 則在本身的內部使用 test 和 include 字段去決定本身在哪個目錄下處理哪一類文件,全部的 rule 最終都在 config.module.rules 中拼接成一個數組。

      const fileRule = {
        test: /\.(png|svg|jpg|gif|woff|woff2)$/,
        use: [{
          loader: 'url-loader',
          options: isDev ? { limit: 2500 } : {
            limit: 2500,
            outputPath: assestPathName,
            publicPath: `/${assestPathName}`
          },
        }],
        include: [appDir],
        exclude: [nodeModuleDir]
      }
      const baseConfig = {
        target: 'web',
        mode,
        entry: { 'app': [path.resolve(appDir, 'app.tsx')] },
        resolve: {
          extensions: [".ts", ".tsx", '.js']
        },
        module: {
          rules: [
            typeScriptRule,
            javaScriptRule,
            modulesStyleRule,
            commonStyleRule,
            fileRule
          ]
        }
      }
    • plugins - 插件

      在 webpack 打包中,不一樣時間段是在作着這個不一樣的事情。而插件則能獲取到這些不一樣的時間點,方便你去作任何事情。沒錯,是任何事情。這就決定了 plugins 的功能是很是普遍的。

      這裏主要說明幾個插件的做用

      • DefinePlugin:定義全局變量,但在 typescript 中使用須要在 typings.d.ts 中把這個變量定義好,否則的話會提出警告。

        同時須要說明一下這裏不是給 __DEV__ 賦值,而是在編譯的時候把 __DEV__ 替換成 true / false。配合上 webpack 的 Tree Shaking 咱們就能很方便設置一些配置文件:在開發環境的配置不會帶在正式環境打包後的代碼中

        // 須要在 typings.d.ts 中定義
          // declare const __DEV__: boolean
          new webpack.DefinePlugin({ __DEV__: isDev }),
        
          // 使用
          const config = __DEV__ ? 'dev' : 'production'
          // DEV 編譯後
          const config = true ? 'dev' : 'production'
          // Tree Shaking 後
          const config = 'dev'
      • MiniCssExtractPlugin 把 CSS 抽離成單獨的文件
  • module.exports 以前的
    在 module.exports 以前的大可能是配置,以及和環境(dev/dep)無關的的 rule / loader 配置。

    // 開發代理服務器配置
    const ip = require('ip')
    ...
    // html Plugin 配置
    const baseHtmlWebpackPluginConfig = {
      filename: `index.html`,
      title: 'title',
      template: path.join(appDir, 'app.html'),
      inject: true
    }

DLL (Dynamic Link Library)

在 webpack.config.js 的文件中其實能夠看到在 production 環境下,使用到 webpack.DllReferencePlugin 。

const dllReferencePlugin = new webpack.DllReferencePlugin({
  context: process.cwd(),
  manifest: require('./dll/dll.manifest.json')
})

而這裏使用到的 dll.manifest.json 文件則是咱們要見的 webpack.dll.config.js 配置下產生的。

webpack.dll.config.js 其實和 webpack.config.js 的正式環境差很少。只不過它只須要處理 ts 或者 js 文件(並且通常是依賴包下的 node_modules)。而它須要引入 webpack.DllPlugin 來導出一個清單文件(manifest.json)。這樣在 webpack.config.js 中真正打包的時候就會跳過 manifest.json 上已經打包的模塊。直接使用 dll.js 提供的模塊。

new webpack.DllPlugin({
  // 動態連接庫的全局變量名稱,須要和 output.library 中保持一致
  name: '[name]',
  // 描述動態連接庫的 manifest.json 文件輸出時的文件名稱
  path: path.resolve(process.cwd(), 'dll', '[name].manifest.json')
})

DLL 的優勢在於咱們無需頻繁打包這些不常常更新的依賴包文件,在正式環境下打包的時候, DLL 相關文件實際上是再也不參與的。確保每次更新後用戶須要再次下載的內容不會變更很大。

eslint 配置

詳見 package.json 下的 eslintConfig 字段

browserslist 配置

詳見 package.json 下的 browserslist 字段

相關文章
相關標籤/搜索