本文目標
從零搭建出一套支持react+less+typescript+mobx的webpack配置
最簡化webpack配置
首頁要初始化yarn和安裝webpack的依賴
yarn init -y
yarn add webpack webpack-cli -D
根目錄下新建webpack.config.js文件,內容如下
const path = require('path'); module.exports = { mode: 'development', // 入口 這里應用程序開始執行 entry: path.resolve(__dirname, 'src/index.tsx'), // 出口 output: { // 輸出文件的目標路徑 path: path.resolve(__dirname, 'dist'), // 輸出的文件名 filename: 'bundle.js', // 輸出解析文件的目錄。靜態資源最終訪問路徑 = output.publicPath + 資源loader或插件等配置路徑 publicPath: '/' } }
使用命令進行打包
webpack --mode production
另外亦可以將命令配置到 package.json 中的 scripts 字段
"scripts": { "build": "webpack --mode production" },
執行命令 yarn build 即可打包
使用模版html
html-webpack-plugin 插件 可以指定template模板文件,將會在output目錄下,生成html文件,並引入打包后的js.
安裝依賴
yarn add html-webpack-plugin -D
在webpack.config.js增加plugins配置
const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { //...other code plugins: [ new HtmlWebpackPlugin({ template: path.resolve(__dirname, 'src/index.html') }) ] }
html-webpack-plugin 插件 還支持title、minify、filename等其他參數
配置webpack-dev-server
webpack-dev-server提供了一個簡單的Web服務器和實時熱更新的能力,有助於開發。
安裝依賴
yarn add webpack-dev-server -D
在webpack.config.js中增加devServer配置
const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { //...other code devServer: { hot: true, port: 3000, open: true, contentBase: path.resolve(__dirname, 'dist'), // 開發模式下寫/就行啦 publicPath: '/', } }
在 package.json 的 scripts 字段中增加 start模式
"scripts": { "start": "webpack-dev-server --mode development", "build": "webpack --mode production" },
這樣我們就可以通過yarn start來啟動服務啦
支持加載css文件
通過使用不同的 style-loader 和 css-loader, 可以將 css 文件轉換成js 文件類型。
安裝依賴
yarn add style-loader css-loader -D
在webpack.config.js中增加loader配置
module.exports = { //other code module: { rules: [ { test: /\.css/, use: ['style-loader', 'css-loader'], exclude: /node_modules/, include: path.resolve(__dirname, 'src') } ] } }
loader 可以配置以下參數:
- test: 匹配處理文件的擴展名的正則表達式
- use: loader名稱
- include/exclude: 手動指定必須處理的文件夾或屏蔽不需要處理的文件夾
- query: 為loader提供額外的設置選項
支持圖片加載
需要引入兩個loader
- file-loader: 解決CSS等文件中的引入圖片路徑問題
- url-loader: 當圖片小於limit的時候會把圖片Base64編碼,大於limit參數的時候還是使用file-loader進行拷貝
如果希望圖片存放在單獨的目錄下,那么需要指定outputPath
安裝依賴
yarn add url-loader file-loader -D
在 webpack.config.js 中增加 loader 的配置(增加在 module.rules 的數組中)。
module.exports = { //other code module: { rules: [ { test: /\.(gif|jpg|png|bmp|eot|woff|woff2|ttf|svg)/, use: [ { loader: 'url-loader', options: { limit: 8192, outputPath: 'images' } } ] } ] } }
支持編譯less
很多前端都喜歡寫less,所以支持less也是需要的。(sass配置方法基本相同)
安裝依賴
yarn add less less-loader -D
在 webpack.config.js 中增加 loader 的配置(module.rules 數組中)。
module.exports = { //other code module: { rules: [ { test: /\.less/, use: ['style-loader', 'css-loader', 'less-loader'], exclude: /node_modules/, include: path.resolve(__dirname, 'src') }, ] } }
支持轉義 ES6/ES7/JSX(react)
安裝ES6/ES7/JSX 轉義需要 Babel 的依賴,支持裝飾器。
yarn add @babel/core babel-loader @babel/preset-env @babel/preset-react @babel/plugin-proposal-decorators @babel/plugin-proposal-object-rest-spread -D
在 webpack.config.js 中增加 loader 的配置(module.rules 數組中)。
module.exports = { //other code module: { rules: [ { test: /\.jsx?$/, use: [ { loader: 'babel-loader', options: { presets: ['@babel/preset-env', '@babel/react'], plugins: [ [ "@babel/plugin-proposal-decorators", { "legacy": true } ] ] } } ], include: path.resolve(__dirname, 'src'), exclude: /node_modules/ }, ] } }
壓縮JS文件
安裝依賴
yarn add uglifyjs-webpack-plugin -D
在 webpack.config.js 中增加 optimization 的配置
const UglifyWebpackPlugin = require('uglifyjs-webpack-plugin'); module.exports = { //other code optimization: { minimizer: [ new UglifyWebpackPlugin({ parallel: 4 }) ] } }
分離出CSS
因為CSS的下載和JS可以並行,當一個HTML文件很大的時候,可以把CSS單獨提取出來加載
安裝依賴
yarn add mini-css-extract-plugin -D
在 webpack.config.js 中增加 plugins 的配置,並且將 'style-loader' 修改為 { loader: MiniCssExtractPlugin.loader}。CSS打包在單獨目錄,那么配置filename。
const MiniCssExtractPlugin = require('mini-css-extract-plugin'); module.exports = { //other code module: { rules: [ { test: /\.css/, use: [{ loader: MiniCssExtractPlugin.loader}, 'css-loader'], exclude: /node_modules/, include: path.resolve(__dirname, 'src') }, { test: /\.less/, use: [{ loader: MiniCssExtractPlugin.loader }, 'css-loader', 'less-loader'], exclude: /node_modules/, include: path.resolve(__dirname, 'src') }, ] }, plugins: [ new MiniCssExtractPlugin({ filename: 'css/[name].css' }) ] }
壓縮CSS文件
安裝依賴
yarn add optimize-css-assets-webpack-plugin -D
在 webpack.config.js 中的 optimization 中增加配置
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin'); module.exports = { //other code optimization: { minimizer: [ new OptimizeCssAssetsWebpackPlugin() ] } }
支持react和mobx
安裝react依賴
yarn add react react-dom
安裝mobx依賴
yarn add mobx mobx-react
支持typescript
安裝依賴
yarn add typescript awesome-typescript-loader -D
安裝react的類型依賴(否則會有命名空間和.d.ts相關報錯)
yarn add @types/react @types/react-dom
在 webpack.config.js 中增加 loader 的配置(module.rules 數組中)。
module.exports = { //other code module: { rules: [ { test: /\.(tsx|ts)?$/, loader: "awesome-typescript-loader", exclude: /node_modules/, include: path.resolve(__dirname, 'src') } ] } }
在根目錄下添加tsconfig.json
{ "compilerOptions": { "baseUrl": ".", "outDir": "build/dist", "module": "esnext", "target": "es5", "lib": ["es6", "dom"], "sourceMap": true, "allowJs": true, "jsx": "react", "moduleResolution": "node", "experimentalDecorators": true, "rootDir": "./", "forceConsistentCasingInFileNames": true, "noImplicitReturns": true, "noImplicitThis": true, "noImplicitAny": false, "importHelpers": true, "strictNullChecks": true, "suppressImplicitAnyIndexErrors": true, "noUnusedLocals": false, "allowSyntheticDefaultImports": true }, "exclude": [ "node_modules", "build", "scripts", "acceptance-tests", "webpack", "jest", "src/setupTests.ts" ] }
在根目錄下添加tslint.json
{ "extends": ["tslint:recommended", "tslint-react", "tslint-config-prettier"], "rules": { "no-empty-interface":false, "no-empty-block":false, "no-unused-expression":false, "object-literal-sort-keys":false, "no-empty":false, "semicolon": [false, "always"], "no-default-export": false, "member-access": true, "ordered-imports": false, "import-sources-order": "any", "named-imports-order": "any", "interface-over-type-literal":false, "jsx-no-lambda":false, "variable-name": [ true, "ban-keywords", "check-format", "allow-leading-underscore", "allow-trailing-underscore", "allow-pascal-case", "allow-snake-case" ], "no-console": false, "no-angle-bracket-type-assertion": false, "jsx-no-string-ref":false, "prefer-for-of":false, "member-ordering":false, "only-arrow-functions":false, "object-literal-shorthand":false }, "linterOptions": { "exclude": [ "config/**/*.js", "node_modules/**/*.ts", "coverage/lcov-report/*.js" ] }, "strict": false }
打包前先清空輸出目錄
安裝依賴
yarn add clean-webpack-plugin -D
在 webpack.config.js 中增加 plugins 的配置
const {CleanWebpackPlugin} = require('clean-webpack-plugin'); module.exports = { //other code plugins: [ new CleanWebpackPlugin() ] }
( 注意3.0版本的clean-webpack-plugin有大改動,需要通過構造函數取出CleanWebpackPlugin再用 )
至此,webpack配置已經基本能滿足react+less+typescript+mobx開發需求。
完整webpack.config.js和package.json文件
webpack.config.js文件
const path = require('path'); // 打包html的插件 const HtmlWebpackPlugin = require('html-webpack-plugin'); // 壓縮JS的插件 const UglifyWebpackPlugin = require('uglifyjs-webpack-plugin'); // 分離css文件 const MiniCssExtractPlugin = require('mini-css-extract-plugin'); // 打包前先清空輸出目錄 const {CleanWebpackPlugin} = require('clean-webpack-plugin'); module.exports = { mode: 'development', // 入口 這里應用程序開始執行 entry: path.resolve(__dirname, 'src/index.tsx'), // 出口 output: { // 所有輸出文件的目標路徑 path: path.resolve(__dirname, 'dist'), // 輸出的文件名 filename: 'bundle.js', // 輸出解析文件的目錄,url 相對於 HTML 頁面, publicPath 上線時配置的是cdn的地址。 // 靜態資源最終訪問路徑 = output.publicPath + 資源loader或插件等配置路徑 publicPath: './' }, devServer: { hot: true, port: 3000, open: true, contentBase: path.resolve(__dirname, 'dist'), publicPath: '/', // stats: 'none' }, module: { rules: [ /* * 支持css * 通過使用不同的 style-loader 和 css-loader, 可以將 css 文件轉換成JS文件類型。 * */ { test: /\.css/, // use: ['style-loader', 'css-loader'], use: [ { loader: MiniCssExtractPlugin.loader }, 'css-loader' ], exclude: /node_modules/, include: path.resolve(__dirname, 'src') }, /* * 支持編譯less和sass * */ { test: /.less/, // use: ['style-loader', 'css-loader', 'less-loader'], use: [ { loader: MiniCssExtractPlugin.loader }, 'css-loader', 'less-loader' ], exclude: /node_modules/, include: path.resolve(__dirname, 'src') }, /* * 支持加載圖片 * file-loader: 解決CSS等文件中的引入圖片路徑問題 * url-loader: 當圖片小於limit的時候會把圖片Base64編碼,大於limit參數的時候還是使用file-loader進行拷貝 * */ { test: /\.(gif|jpg|png|bmp|eot|woff|woff2|ttf|svg)/, use: [ { loader: 'url-loader', options: { limit: 1, outputPath: 'images' } } ] }, /* * 支持轉義 ES6/ES7/JSX ,支持react * ES6/ES7/JSX 轉義需要 Babel 的依賴,支持裝飾器。 * */ { test: /\.jsx?$/, use: [ { loader: "babel-loader", options: { presets: ['@babel/preset-env', '@babel/react'], plugins: [ [ "@babel/plugin-proposal-decorators", // "@babel/plugin-proposal-class-properties", { "legacy": true } ] ] } } ], exclude: /node_modules/, include: path.resolve(__dirname, 'src') }, /* * 支持轉義 支持typescript * ES6/ES7/JSX 轉義需要 Babel 的依賴,支持裝飾器。 * */ { test: /\.(tsx|ts)?$/, loader: "awesome-typescript-loader", exclude: /node_modules/, include: path.resolve(__dirname, 'src') } ] }, optimization: { minimizer: [ new UglifyWebpackPlugin({ parallel: 4 }) ] }, plugins: [ new HtmlWebpackPlugin({ template: path.resolve(__dirname, 'public/index.html') }), new MiniCssExtractPlugin({ filename:'css/[name].css' }), new CleanWebpackPlugin() ] };
package.json文件
{ "name": "webpack_cli", "version": "1.0.0", "main": "index.js", "license": "MIT", "scripts": { "start": "webpack-dev-server --mode development", "build": "webpack --mode production" }, "devDependencies": { "@babel/core": "^7.5.5", "@babel/plugin-proposal-decorators": "^7.4.4", "@babel/plugin-proposal-object-rest-spread": "^7.5.5", "@babel/preset-env": "^7.5.5", "@babel/preset-react": "^7.0.0", "@types/react": "^16.9.2", "@types/react-dom": "^16.8.5", "awesome-typescript-loader": "^5.2.1", "babel-loader": "^8.0.6", "clean-webpack-plugin": "^3.0.0", "css-loader": "^3.2.0", "file-loader": "^4.2.0", "html-webpack-plugin": "^3.2.0", "less": "^3.10.1", "less-loader": "^5.0.0", "mini-css-extract-plugin": "^0.8.0", "optimize-css-assets-webpack-plugin": "^5.0.3", "style-loader": "^1.0.0", "typescript": "^3.5.3", "uglifyjs-webpack-plugin": "^2.2.0", "url-loader": "^2.1.0", "webpack": "^4.39.2", "webpack-cli": "^3.3.7", "webpack-dev-server": "^3.8.0" }, "dependencies": { "mobx": "^5.13.0", "mobx-react": "^6.1.3", "react": "^16.9.0", "react-dom": "^16.9.0" } }
學習更多webpack配置請進入webpack官網 webpack官網鏈接
本文配置將持續升級優化