React+TypeScript+webpack4多入口配置

資源

  • React-16.8.*
  • react-router-dom-4.3.*
  • TypeScript-3.5.*
  • webpack-4.*
  • eslint-5.16.*

項目目錄

├── dist # 打包結果目錄
│   ├── demo1 //類別demo1的打包結果
│    │    ├── demo1.himl
│   │    ├── demo1.js
│    │    └── demo1.css
│   └── demo2 ... //類別demo2的打包結果
├── src # 業務資源文件目錄
│    ├── category //項目分類
│    │    ├── demo1
│    │    ├── demo2
│    │    └── ...
│    ├── components //公共組件
│    ├── util //公共資源
│    └── custom.d.ts //項目全局變量聲明文件
├── index.html //項目啓動入口
├── .gitignore //git忽略文件
├── .eslintrc.js //eslint校驗配置
├── package.json //依賴包
├── tsconfig.json //ts配置
├── webpack.config.build.js //webpack打包
├── webpack.config.base.js //webpack基礎配置
└── webpack.config.js //項目啓動配置

前言

對於複雜或多人開發的 React 項目來講,管理和使用每一個組件的 propsstate 或許會成爲一件讓人頭痛的事情,而爲每個組件寫文檔,成本也會比較大,對項目的開發效率也不是最理想的。css

TypescriptReact 帶來不少好處:html

  • 在組件頭部定義 interface,讓每一個人在拿到組件的第一時間就能夠很明確知道該組件須要使用的 propsstate
  • 在編譯中發現問題,減小運行時的報錯;
  • 能夠在編輯器中實現實時類型校驗、引用查詢;
  • 約束類型,在混合多語言環境中下降風險,等。

需求

要搭建一個React+TypeScript+webpack的項目的話,通常都是團隊開發多人多文件項目,在搭建以前須要優先考慮如下幾個方面:node

  • 開發體驗
  • 項目打包
  • 團隊規範

安裝

  • 前置安裝
    首先須要全局安裝typescript,這裏默認你們都已經安裝了node以及npmreact

    npm install -g typescript
  • 首先新建文件夾並進入webpack

    mkdir tsDemo && cd tsDemo
  • 而後進行初始化,生成package.jsontsconfig.jsongit

    npm init -y && tsc --init
  • 安裝開發工具web

    npm install-D webpack webpack-cli webpack-dev-server
  • 安裝react相關
    由於須要整合ts,而react本來的包是不包含驗證包的,因此這裏也須要安裝相關ts驗證包typescript

    npm install -S react react-dom
    npm install -D @types/react @types/react-dom
  • 安裝ts-loadernpm

    npm install -D ts-loader
  • 以上是基本的 後續會貼出項目demo裏面包含全部依賴包

webpack配置

添加webpack文件

根目錄下新建webpack.config.base.js、webpack.config.build.js、webpack.config.js文件json

touch webpack.config.base.js webpack.config.build.js webpack.config.js
  1. entry:入口文件(你要打包,就告訴我打包哪些)
  2. output:出口文件(我打包完了,給你放到哪裏)
  3. resolve: 尋找模塊所對應的文件
  4. module:模塊(放lorder,編譯瀏覽器不認識的東西)
  5. plugins:插件(輔助開發,提升開發效率)
  6. externals:打包忽略
  7. devServer:服務器(webpack提供的本地服務器)
  8. mode:模式,分爲開發模式、生產模式。此爲4.X裏新增的

配置entry入口文件

由於大部分項目是多入口,多類別的,全部入口配置時不要配置單一入口

const fs = require("fs");
const path = require("path");
const optimist = require("optimist");

const cateName = optimist.argv.cate;
let entryObj = {};
const srcPath = `${__dirname}/src`;
//獲取當前項目要啓動或者打包的基礎路徑
const entryPath = `${srcPath}/category/`;
//未指定類別 啓動或者打包全部類別
//如:npm run dev 或者npm run build
if (cateName == true) {
    fs.readdirSync(entryPath).forEach((cateName, index) => {
        // cateName/cateName指定輸出路徑爲entryname
        if (cateName != "index.html" && cateName != ".DS_Store") entryObj[`${cateName}/${cateName}`] = `${entryPath + cateName}/${cateName}.tsx`;
    });
} else if (cateName.indexOf(",")) {
    // 一次指定多個類別 類別之間以","分割
    //如:npm run dev erhsouche,huoche 
    let cateNameArray = cateName.split(",");
    for (let i = 0; i < cateNameArray.length; i++) {
        entryObj[`${cateNameArray[i]}/${cateNameArray[i]}`] = `${entryPath + cateNameArray[i]}/${
            cateNameArray[i]
        }.tsx`;
    }
} else {
    // 打包單個入口文件
    //如:npm run dev ershouche
    entryObj[`${cateName}/${cateName}`] = `${entryPath + cateName}/${cateName}.tsx`;
}
const webpackConfig = {
    entry: entryObj,
}
module.exports = {
    webpackConfig,
    entryObj
};

配置output出口文件

const webpackConfig = {
    output: {
        //輸出文件名稱以當前傳入的cate類別名稱命名
        filename: "[name].js", 
        //輸出到根目錄下的dist目錄中
        path: path.resolve(__dirname, "dist"),
        publicPath: "/",
    },
}

配置resolve

須要import xxx from 'xxx'這樣的文件的話須要在webpack中的resolve項中配置extensions,這樣之後引入文件就不須要帶擴展名

const webpackConfig = {
    resolve: {
        extensions: [".tsx", ".ts", ".js", ".jsx", ".json"],
        //配置項經過別名來把原導入路徑映射成一個新的導入路徑。
        alias: {
            images: path.join(__dirname, "src/util/img")
        },
        // 使用絕對路徑指明第三方模塊存放的位置,以減小搜索步驟
        modules: [path.resolve(__dirname, "node_modules")] 
    },
}

配置module

概念

webpack中任何一個東西都稱爲模塊,js就不用說了。一個css文件,一張圖片、一個less文件都是一個模塊,都能用導入模塊的語法(commonjsrequireES6import)導入進來。webpack自身只能讀懂js類型的文件,其它的都不認識。可是webpack卻能編譯打包其它類型的文件,像ES6JSXlesstypeScript等,甚至cssimages也是Ok的,而想要編譯打包這些文件就須要藉助loader

loader就像是一個翻譯員,瀏覽器不是不認識這些東西麼?那好交給loader來辦,它能把這些東西都翻譯成瀏覽器認識的語言。loader描述了webpack如何處理非js模塊,而這些模塊想要打包loader必不可少,因此它在webpack裏顯得異常重要。loader跟插件同樣都是模塊,想要用它須要先安裝它,使用的時候把它放在module.rules參數裏,rules翻譯過來的意思就是規則,因此也能夠認爲loader就是一個用來處理不一樣文件的規則

所需loader

  • ts-loader

    編譯TypeScript文件

    npm install ts-loader -D
  • url-loader

    處理css中的圖片資源時,咱們經常使用的兩種loader是file-loader或者url-loader,二者的主要差別在於。url-loader能夠設置圖片大小限制,當圖片超過限制時,其表現行爲等同於file-loader,而當圖片不超過限制時,則會將圖片以base64的形式打包進css文件,以減小請求次數。

    npm install url-loader -D
  • css處理所需loader
    css-loader 處理css

    sass-loader 編譯處理scss

    sass-resources-loader 全局註冊變量

  • html-loader
    處理.html文件

module完整配置

const webpackConfig = {
    module: {
        rules: [
            //處理tsx文件
            { test: /\.(tsx|ts)?$/, use: ["ts-loader"], include: path.resolve(__dirname, "src") },
            //處理圖片資源
            {
                test: /\.(png|jpe?g|jpg|gif|woff|eot|ttf|svg)/,
                use: [
                    // 對非文本文件採用file-loader加載
                    {
                        loader: "url-loader",
                        options: {
                            limit: 1024 * 30, // 30KB如下的文件
                            name: "images/[name].[hash:8].[ext]",
                        }
                    }
                ],
            },
            //處理css和scss
            {
                test: /\.(css|scss)$/,
                use: [
                    //css單獨打包
                    MiniCssExtractPlugin.loader,
                    {
                        loader: "css-loader"
                    },
                    {
                        loader: "postcss-loader",
                        options: {
                            plugins: () => [require("autoprefixer")],
                            sourceMap: true
                        }
                    },
                    {
                        loader: "sass-loader",
                        options: {
                            sourceMap: true
                        }
                    },
                    {
                        loader: "sass-resources-loader",
                        options: {
                            resources: ["./skin/mixin.scss", "./skin/base.scss"]
                        }
                    }
                ],
                exclude: path.resolve(__dirname, "node_modules")
            },
            {
                test: /\.html$/,
                use: {
                    loader: "html-loader",
                }
            },
            { test: /src\/containers(\/.*).(tsx|ts)/, loader: "bundle-loader?lazy!ts-loader" },
            { enforce: "pre", test: /\.js$/, loader: "source-map-loader" }
        ]
    },
}

配置plugins

plugins裏面放的是插件,插件的做用在於提升開發效率,可以解放雙手,讓咱們去作更多有意義的事情。一些很low的事就通通交給插件去完成。

const webpackConfig = {
    plugins: [
        //清除文件
        new CleanWebpackPlugin(),
        //css單獨打包
        new MiniCssExtractPlugin({
            filename: "[name].css",
            chunkFilename: "[name].css"
        }),
        // 引入熱更新插件
        new webpack.HotModuleReplacementPlugin() 
    ]
}

配置externals

若是須要引用一個庫,可是又不想讓webpack打包(減小打包的時間),而且又不影響咱們在程序中以CMD、AMD或者window/global全局等方式進行使用(通常都以import方式引用使用),那就能夠經過配置externals。

const webpackConfig = {
    //項目編譯打包是忽略這些依賴包
    externals: {
        react: "React",
        "react-dom": "ReactDOM",
        "react-redux": "ReactRedux",
    }
}

配置mode

modewebpack4新增的一條屬性,它的意思爲當前開發的環境。mode的到來減小了不少的配置,它內置了不少的功能。相較之前的版本提高了不少,減小了不少專門的配置

  1. 提高了構建速度
  2. 默認爲開發環境,不須要專門配置
  3. 提供壓縮功能,不須要藉助插件
  4. 提供SouceMap,不須要專門配置

mode分爲兩種環境,一種是開發環境(development),一種是生產環境(production)。開發環境就是咱們寫代碼的環境,生產環境就是代碼放到線上的環境。這兩種環境的最直觀區別就是,開發環境的代碼不提供壓縮,生產環境的代碼提供壓縮。

配置devServer

const webpackConfig = {
    devServer: {
        // 本地服務器所加載的頁面所在的目錄
        contentBase: srcPath, 
        //熱更新
        hot: true,
        //服務端口
        port: "7788",
        // 是否向Chunk中注入代理客戶端,默認注入
        inline: true, 
        // publicPath: '/dist/',
        historyApiFallback: {
            index: "template.html",
        },
        //默認檢查hostname
        disableHostCheck: true,
        compress: true,
        open: true // 自動打開首頁
    }
}
相關文章
相關標籤/搜索