├── 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
項目來講,管理和使用每一個組件的 props
、 state
或許會成爲一件讓人頭痛的事情,而爲每個組件寫文檔,成本也會比較大,對項目的開發效率也不是最理想的。css
Typescript
給 React
帶來不少好處:html
interface
,讓每一個人在拿到組件的第一時間就能夠很明確知道該組件須要使用的 props
和 state
;要搭建一個React+TypeScript+webpack的項目的話,通常都是團隊開發多人多文件項目,在搭建以前須要優先考慮如下幾個方面:node
前置安裝
首先須要全局安裝typescript,這裏默認你們都已經安裝了node以及npmreact
npm install -g typescript
首先新建文件夾並進入webpack
mkdir tsDemo && cd tsDemo
而後進行初始化,生成package.json
和tsconfig.json
git
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-loader
npm
npm install -D ts-loader
根目錄下新建webpack.config.base.js、webpack.config.build.js、webpack.config.js文件json
touch webpack.config.base.js webpack.config.build.js webpack.config.js
entry
:入口文件(你要打包,就告訴我打包哪些)output
:出口文件(我打包完了,給你放到哪裏)resolve
: 尋找模塊所對應的文件module
:模塊(放lorder,編譯瀏覽器不認識的東西)plugins
:插件(輔助開發,提升開發效率)externals
:打包忽略devServer
:服務器(webpack提供的本地服務器)mode
:模式,分爲開發模式、生產模式。此爲4.X裏新增的由於大部分項目是多入口,多類別的,全部入口配置時不要配置單一入口
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 };
const webpackConfig = { output: { //輸出文件名稱以當前傳入的cate類別名稱命名 filename: "[name].js", //輸出到根目錄下的dist目錄中 path: path.resolve(__dirname, "dist"), publicPath: "/", }, }
須要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")] }, }
在webpack
中任何一個東西都稱爲模塊,js
就不用說了。一個css
文件,一張圖片、一個less
文件都是一個模塊,都能用導入模塊的語法(commonjs
的require
,ES6
的import
)導入進來。webpack
自身只能讀懂js
類型的文件,其它的都不認識。可是webpack
卻能編譯打包其它類型的文件,像ES6
、JSX
、less
、typeScript
等,甚至css
、images
也是Ok的,而想要編譯打包這些文件就須要藉助loader
loader
就像是一個翻譯員,瀏覽器不是不認識這些東西麼?那好交給loader
來辦,它能把這些東西都翻譯成瀏覽器認識的語言。loader
描述了webpack
如何處理非js
模塊,而這些模塊想要打包loader
必不可少,因此它在webpack
裏顯得異常重要。loader
跟插件同樣都是模塊,想要用它須要先安裝它,使用的時候把它放在module.rules
參數裏,rules
翻譯過來的意思就是規則,因此也能夠認爲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
sass-loader 編譯處理scss
sass-resources-loader 全局註冊變量
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
裏面放的是插件,插件的做用在於提升開發效率,可以解放雙手,讓咱們去作更多有意義的事情。一些很low的事就通通交給插件去完成。
const webpackConfig = { plugins: [ //清除文件 new CleanWebpackPlugin(), //css單獨打包 new MiniCssExtractPlugin({ filename: "[name].css", chunkFilename: "[name].css" }), // 引入熱更新插件 new webpack.HotModuleReplacementPlugin() ] }
若是須要引用一個庫,可是又不想讓webpack打包(減小打包的時間),而且又不影響咱們在程序中以CMD、AMD或者window/global全局等方式進行使用(通常都以import方式引用使用),那就能夠經過配置externals。
const webpackConfig = { //項目編譯打包是忽略這些依賴包 externals: { react: "React", "react-dom": "ReactDOM", "react-redux": "ReactRedux", } }
mode
是webpack4
新增的一條屬性,它的意思爲當前開發的環境。mode
的到來減小了不少的配置,它內置了不少的功能。相較之前的版本提高了不少,減小了不少專門的配置
- 提高了構建速度
- 默認爲開發環境,不須要專門配置
- 提供壓縮功能,不須要藉助插件
- 提供
SouceMap
,不須要專門配置
mode
分爲兩種環境,一種是開發環境(development
),一種是生產環境(production
)。開發環境就是咱們寫代碼的環境,生產環境就是代碼放到線上的環境。這兩種環境的最直觀區別就是,開發環境的代碼不提供壓縮,生產環境的代碼提供壓縮。
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 // 自動打開首頁 } }