摘要:安裝配置加載器配置配置文件配置支持自定義的預(yù)設(shè)或插件只有配置了這兩個才能讓生效,多帶帶的安裝是無意義的。
想閱讀更多優(yōu)質(zhì)文章請猛戳GitHub博客,一年百來篇優(yōu)質(zhì)文章等著你!
最新React全家桶實戰(zhàn)使用配置指南這篇文檔 是呂小明老師結(jié)合以往的項目經(jīng)驗 加上自己本身對react webpack redux理解寫下的總結(jié)文檔,總共耗時一周總結(jié)下來的,希望能對讀者能夠有收獲, 我是在這基礎(chǔ)多些加工!
目錄1.版本說明
2.目錄結(jié)構(gòu)
3.初始化項目
4.webpack
5.react
6.配置loader(sass,jsx))
7.引入babel
8.使用HtmlWebpackPlugin
9.redux
10.使用webpack-dev-server
11.多入口頁面配置
12.如何理解entry point(bundle),chunk,module
13.多入口頁面html配置
14.模塊熱替換(Hot Module Replacement)
15.使用ESLint
16.使用react-router
17.使用redux-thunk
18.使用axios和async/await
19.Code Splitting
20.使用CommonsChunkPlugin
版本說明由于構(gòu)建相關(guān)例如webpack,babel等更新的較快,所以本教程以下面各種模塊的版本號為主,切勿輕易修改或更新版本。
"dependencies": { "babel-core": "^6.26.3", "babel-eslint": "^8.2.3", "babel-loader": "^7.1.4", "babel-plugin-transform-async-to-generator": "^6.24.1", "babel-plugin-transform-runtime": "^6.23.0", "babel-preset-es2015": "^6.24.1", "babel-preset-react": "^6.24.1", "babel-preset-stage-0": "^6.24.1", "babel-preset-stage-3": "^6.24.1", "css-loader": "^0.28.11", "eslint": "^4.19.1", "eslint-loader": "^2.0.0", "eslint-plugin-react": "^7.9.1", "file-loader": "^1.1.11", "history": "^4.7.2", "html-webpack-plugin": "^3.2.0", "react": "^16.4.0", "react-dom": "^16.4.0", "react-hot-loader": "^4.0.0", "react-redux": "^5.0.7", "react-router-dom": "^4.3.1", "react-router-redux": "^5.0.0-alpha.9", "redux": "^4.0.0", "sass-loader": "^7.0.3", "style-loader": "^0.21.0", "url-loader": "^1.0.1", "webpack": "^4.12.0", "webpack-cli": "^3.0.3", "webpack-dev-server": "^3.1.1" }目錄結(jié)構(gòu)
開發(fā)和發(fā)布版本的配置文件是分開的,多入口頁面的目錄結(jié)構(gòu)。
react-family/ | |──dist/ * 發(fā)布版本構(gòu)建輸出路徑 | |──dev/ * 調(diào)試版本構(gòu)建輸出路徑 | |──src/ * 工具函數(shù) | | | |—— component/ * 各頁面公用組件 | | | |—— page/ * 頁面代碼 | | |—— index/ * 頁面代碼 | | | |—— Main/ * 組件代碼 | | | | |—— Main.jsx * 組件jsx | | | | |—— Main.scss * 組件css | | | | | |—— detail/ * 頁面代碼 | | | |—— static/ * 靜態(tài)文件js,css | | |──webpack.config.build.js * 發(fā)布版本使用的webpack配置文件 |──webpack.config.dev.js * 調(diào)試版本使用的webpack配置文件 |──.eslint * eslint配置文件 |__.babelrc * babel配置文件初始化項目
1.創(chuàng)建文件夾
mkdir react-family-bucket
2.初始化npm
cd react-family-bucket npm init
如果有特殊需要,可以填入自己的配置,一路回車下來,會生成一個package.json,里面是你項目的基本信息,后面的npm依賴安裝也會配置在這里。
webpack1.安裝webpack
npm install webpack@4.12.0 --save or npm install webpack@4.12.0 --g
--save 是將當前webpack安裝到react-family-bucket下的/node_modules。
--g 是將當前webpack安裝到全局下面,可以在node的安裝目錄下找到全局的/node_modules。
2.配置webopack配置文件
touch webpack.config.dev.js
3.新建一個app.js
touch app.js
寫入基本的webpack配置,可以參考這里:
const path = require("path"); const srcRoot = "./src"; module.exports = { // 輸入配置 entry: [ "./app.js" ],, // 輸出配置 output: { path: path.resolve(__dirname, "./dev"), filename: "bundle.min.js" }, };
3.執(zhí)行webpack命令
如果是全局安裝:
webpack --config webpack.config.dev.js
如果是當前目錄安裝:
./node_modules/.bin/webpack --config webpack.config.dev.js
為了方便我們使用,可以在package.json中 scripts 添加執(zhí)行命令:
"scripts": { "dev": "./node_modules/.bin/webpack --config webpack.config.dev.js", },
執(zhí)行npm run dev命令之后,會發(fā)現(xiàn)需要安裝webpack-cli,(webpack4之后需要安裝這個)
npm install webpack-cli --save
安裝后,執(zhí)行 npm run dev 會發(fā)現(xiàn)控制臺有個警告 WARNING in configuration ,去除WARNING in configuration 警告,在webpack.config.dev.js 增加一個配置即可:
... mode: "development" ...
成功之后會在dev下面生成bundle.min.js代表正常。
如果想要動態(tài)監(jiān)聽文件變化需要在命令后面添加 --watch。
react1.安裝react
npm install react react-dom --save
2.創(chuàng)建page目錄和index頁面文件:
mkdir src mkdir page cd page
3.創(chuàng)建index
mkdir index cd index & touch index.js & touch index.html
index.js
import ReactDom from "react-dom"; import Main from "./Main/Main.jsx"; ReactDom.render(, document.getElementById("root"));
index.html
index
4.創(chuàng)建Main組件
import React from "react"; class Main extends React.Component { constructor(props) { super(props); } render() { return (Main); } } export default Main;
5.修改webpack配置入口文件
entry: [ path.resolve(srcRoot,"./page/index/index.js") ],配置loader
1.處理樣式文件需要這些loader:
css-loader
sass-loader
style-loader
npm install css-loader sass-loader style-loader file-loader --save
配置:
module: { // 加載器配置 rules: [ { test: /.css$/, use: ["style-loader", "css-loader"], include: path.resolve(srcRoot)}, { test: /.scss$/, use: ["style-loader", "css-loader", "sass-loader"], include: path.resolve(srcRoot)} ] },
2.url-loader 處理處理靜態(tài)文件
npm install url-loader --save
配置:
module: { // 加載器配置 rules: [ { test: /.(png|jpg|jpeg)$/, use: "url-loader?limit=8192&name=images/[name].[hash].[ext]", include: path.resolve(srcRoot)} ] },
limit:表示超過多少就使用base64來代替,單位是byte
name:可以設(shè)置圖片的路徑,名稱和是否使用hash 具體參考這里
引入babelbebel是用來解析es6語法或者是es7語法分解析器,讓開發(fā)者能夠使用新的es語法,同時支持jsx,vue等多種框架。
1.安裝babel
babel-core
babel-loader
npm install babel-core babel-loader --save
配置:
module: { // 加載器配置 rules: [ { test: /.(js|jsx)$/, use: [{loader:"babel-loader"}] ,include: path.resolve(srcRoot)}, ] },
2.babel配置文件:.babelrc
touch .babelrc
配置:
{ "presets": [ "es2015", "react", "stage-0" ], "plugins": [] }
babel支持自定義的預(yù)設(shè)(presets)或插件(plugins),只有配置了這兩個才能讓babel生效,多帶帶的安裝babel是無意義的。
presets:代表babel支持那種語法(就是你用那種語法寫),優(yōu)先級是從下往上,state-0|1|2|..代表有很多沒有列入標準的語法回已state-x表示,參考這里
plugins:代表babel解析的時候使用哪些插件,作用和presets類似,優(yōu)先級是從上往下。
依次安裝:
babel-preset-es2015
babel-preset-react
babel-preset-stage-0
npm install babel-preset-es2015 babel-preset-react babel-preset-stage-0 --save
3.babel-polyfill是什么?
我們之前使用的babel,babel-loader 默認只轉(zhuǎn)換新的 JavaScript 語法,而不轉(zhuǎn)換新的 API。例如,Iterator、Generator、Set、Maps、Proxy、Reflect、Symbol、Promise 等全局對象,以及一些定義在全局對象上的方法(比如 Object.assign)都不會轉(zhuǎn)譯。如果想使用這些新的對象和方法,必須使用 babel-polyfill,為當前環(huán)境提供一個墊片。
npm install --save babel-polyfill
4.transform-runtime 有什么區(qū)別?
當使用babel-polyfill時有一些問題:
默認會引入所有babel支持的新語法,這樣就會導(dǎo)致你的文件代碼非常龐大。
通過向全局對象和內(nèi)置對象的prototype上添加方法來達成目的,造成全局變量污染。
這時就需要transform-runtime來幫我們有選擇性的引入:
npm install --save babel-plugin-transform-runtime
配置文件:
{ "plugins": [ ["transform-runtime", { "helpers": false, "polyfill": false, "regenerator": true, "moduleName": "babel-runtime" }] ] }使用HtmlWebpackPlugin
記得我們之前新建的index.html么 我們執(zhí)行構(gòu)建命令之后并沒有將index.html打包到dev目錄下 我們需要HtmlWebpackPlugin來將我們output的js和html結(jié)合起來:
npm install html-webpack-plugin --save
配置:
const HtmlWebpackPlugin = require("html-webpack-plugin"); ... plugins: [ new HtmlWebpackPlugin({ filename: path.resolve(devPath, "index.html"), template: path.resolve(srcRoot, "./page/index/index.html"), }) ]
filename:可以設(shè)置html輸出的路徑和文件名
template:可以設(shè)置已哪個html文件為模版
更多參數(shù)配置可以參考這里
redux關(guān)于redux的使用可以參考阮一峰老師的入門教程
1.安裝redux
redux
react-redux
npm install redux react-redux --save
1.新建reducers,actions目錄和文件
|—— index/ |—— Main/ * 組件代碼 | |—— Main.jsx * 組件jsx | |—— Main.scss * 組件css | |—— actions/ | |—— actionTypes.js * action常量 | |—— todoAction.js * action | |—— reducers/ | |—— todoReducer.js * reducer | |—— store.js | |—— index.js
2.修改代碼,引入redux,這里以一個redux todo為demo例子:
index.js
import ReactDom from "react-dom"; import React from "react"; import Main from "./Main/Main.jsx"; import store from "./store.js"; import { Provider } from "react-redux"; ReactDom.render(, document.getElementById("root"));
store.js
import { createStore } from "redux"; import todoReducer from "./reducers/todoReducer.js"; const store = createStore(todoReducer); export default store;
tabReducer.js
import { ADD_TODO } from "../actions/actionTypes.js"; const initialState = { todoList: [] }; const addTodo = (state, action) => { return { ...state, todoList: state.todoList.concat(action.obj) } } const todoReducer = (state = initialState, action) => { switch(action.type) { case ADD_TODO: return addTodo(state, action); default: return state; } }; export default todoReducer;
Main.jsx
import React from "react"; import { connect } from "react-redux"; import { addTodo } from "../actions/todoAction.js"; class Main extends React.Component { onClick(){ let text = this.refs.input; this.props.dispatch(addTodo({ text: text.value })) } render() { return (); } } export default connect( state => ({ todoList: state.todoList }) )(Main);{this.props.todoList.map((item, index)=>{ return
- {item.text}
})}
todoAction.js
import { ADD_TODO } from "./actionTypes.js"; export const addTodo = (obj) => { return { type: ADD_TODO, obj: obj }; };使用webpack-dev-server
webpack-dev-server是一個小型的Node.js Express服務(wù)器,它使用webpack-dev-middleware來服務(wù)于webpack的包。
1.安裝
npm install webpack-dev-server --save
修改在package.json中添加的執(zhí)行命令:
"scripts": { "dev": "./node_modules/.bin/webpack-dev-server --config webpack.config.dev.js", },
2.配置webpack配置文件:
devServer: { "contentBase": devPath, "compress": true, },
contentBase: 表示server文件的根目錄
compress: 表示開啟gzip
更多的配置文檔參考這里
webpack-dev-server默認情況下會將output的內(nèi)容放在內(nèi)存中,是看不到物理的文件的,如果想要看到物理的dev下面的文件可以安裝write-file-webpack-plugin這個插件。
webpack-dev-server默認會開啟livereload功能
3.devtool功能:
具體來說添加了devtool: "inline-source-map"之后,利用source-map你在chrome控制臺看到的source源碼都是真正的源碼,未壓縮,未編譯前的代碼,沒有添加,你看到的代碼是真實的壓縮過,編譯過的代碼,更多devtool的配置可以參考這里。
多入口文件配置在之前的配置中,都是基于單入口頁面配置的,entry和output只有一個文件,但是實際項目很多情況下是多頁面的,在配置多頁面時,有2中方法可以選擇:
1.在entry入口配置時,傳入對象而不是多帶帶數(shù)組,output時利用[name]關(guān)鍵字來區(qū)分輸出文件例如:
entry: { index: [path.resolve(srcRoot,"./page/index/index1.js"),path.resolve(srcRoot,"./page/index/index2.js")], detail: path.resolve(srcRoot,"./page/detail/detail.js"), home: path.resolve(srcRoot,"./page/home/home.js"), }, output: { path: path.resolve(__dirname, "./dev"), filename: "[name].min.js" },
2.通過node動態(tài)遍歷需要entry point的目錄,來動態(tài)生成entry:
const pageDir = path.resolve(srcRoot, "page"); function getEntry() { let entryMap = {}; fs.readdirSync(pageDir).forEach((pathname)=>{ let fullPathName = path.resolve(pageDir, pathname); let stat = fs.statSync(fullPathName); let fileName = path.resolve(fullPathName, "index.js"); if (stat.isDirectory() && fs.existsSync(fileName)) { entryMap[pathname] = fileName; } }); return entryMap; } { ... entry: getEntry() ... }
本demo采用的是第二中寫法,能夠更加靈活。
如何理解entry point(bundle),chunk,module在webpack中,如何理解entry point(bundle),chunk,module?
根據(jù)圖上的表述,我這里簡單說一下便于理解的結(jié)論:
配置中每個文件例如index1.js,index2.js,detail.js,home.js都屬于entry point.
entry這個配置中,每個key值,index,detail,home都相當于chunk。
我們在代碼中的require或者import的都屬于module,這點很好理解。
chunk的分類比較特別,有entry chunk,initial chunk,normal chunk,參考這個文章
正常情況下,一個chunk對應(yīng)一個output,在使用了CommonsChunkPlugin或者require.ensure之后,chunk就變成了initial chunk,normal chunk,這時,一個chunk對應(yīng)多個output。
理解這些概念對于后續(xù)使用webpack插件有很大的幫助。
多入口頁面html配置之前我們配置HtmlWebpackPlugin時,同樣采用的是但頁面的配置,這里我們將進行多頁面改造,entryMap是上一步得到的entry:
function htmlAarray(entryMap) { let htmlAarray = []; Object.keys(entryMap).forEach(function(key){ let fullPathName = path.resolve(pageDir, key); let fileName = path.resolve(fullPathName, key + ".html") if (fs.existsSync(fileName)) { htmlAarray.push(new HtmlWebpackPlugin({ chunks: key, // 注意這里的key就是chunk filename: key + ".html", template: fileName, inlineSource: ".(js|css)" })) } }); return htmlAarray; }
修改plugin配置:plugins: [ ... ].concat(htmlMap)模塊熱替換(Hot Module Replacement)
模塊熱替換 (Hot Module Replacement 或 HMR)是 webpack 提供的最有用的功能之一。它允許在運行時更新各種模塊,而無需進行完全刷新,很高大上有木有!
下面說一下配置方法,它需要結(jié)合devServer使用:
devServer: { hot: true // 開啟HMR },
開啟plugin:
const webpack = require("webpack"); plugins: [ new webpack.NamedModulesPlugin(), new webpack.HotModuleReplacementPlugin(), ].concat(htmlMap)
結(jié)合React一起使用:
1.安裝react-hot-loader
npm install react-hot-loader --save
并新建一個Container.jsx:
import React from "react"; import Main from "./Main.jsx"; import { hot } from "react-hot-loader" class Container extends React.Component { render() { return } } export default hot(module)(Container);
結(jié)合redux:如果項目沒有使用redux,可以無需配置后面2步
2.修改store.js新增下面代碼,為了讓reducer也能實時熱替換
if (module.hot) { module.hot.accept("./reducers/todoReducer.js", () => { const nextRootReducer = require("./reducers/todoReducer.js").default; store.replaceReducer(nextRootReducer); }); }
3.修改index.js
import ReactDom from "react-dom"; import React from "react"; import Container from "./Main/Container.jsx"; import store from "./store.js"; import { Provider } from "react-redux"; ReactDom.render(, document.getElementById("root"));
當控制臺看到[WDS] Hot Module Replacement enabled.代表開啟成功
使用ESLintESLint 是眾多 Javascript Linter 中的其中一種,其他比較常見的還有 JSLint 跟 JSHint,之所以用 ESLint 是因為他可以自由選擇要使用哪些規(guī)則,也有很多現(xiàn)成的 plugin 可以使用,另外他對 ES6 還有 JSX 的支持程度跟其他 linter 相比之下也是最高的。
1.安裝ESLint
npm install eslint eslint-loader babel-eslint --save
其中eslint-loader是將webpack和eslint結(jié)合起來在webpack的配置文件中新增一個eslint-loader種,修改如下:
{ test: /.(js|jsx)$/, use: [{loader:"babel-loader"},{loader:"eslint-loader"}] ,include: path.resolve(srcRoot)},
2.新建.eslintrc配置文件,將parser配置成babel-eslint
{ "extends": ["eslint:recommended"], "parser": "babel-eslint", "globals": { }, "rules": { } }
3.安裝eslint-plugin-react:
npm install eslint-plugin-react --save
說明一下,正常情況下每個eslint規(guī)則都是需要在rule下面配置,如果什么都不配置,其實本身eslint是不生效的。
eslint本身有很多默認的規(guī)則模版,可以通過extends來配置,默認可以使用eslint:recommended。
在使用react開發(fā)時可以安裝eslint-plugin-react來告知使用react專用的規(guī)則來lint。
修改.eslintrc配置文件,增加rules,更多rules配置可以參考這里
{ "extends": ["eslint:recommended","plugin:react/recommended"], "parser": "babel-eslint", "globals": { "window": true, "document": true, "module": true, "require": true }, "rules": { "react/prop-types" : "off", "no-console" : "off" } }使用react-router
react-router強大指出在于方便代碼管理,結(jié)合redux使用更加強大,同時支持web,native更多參考這里
1.安裝react-router-dom
npm install react-router-dom --save
2.如果項目中用了redux,可以安裝react-router-redux
npm install react-router-redux@next history --save
3.修改代碼:
index.js
import ReactDom from "react-dom"; import React from "react"; import Container from "./Main/Container.jsx"; import { store, history } from "./store.js"; import { Provider } from "react-redux"; import createHistory from "history/createHashHistory"; import { ConnectedRouter } from "react-router-redux"; const history = createHistory(); ReactDom.render(, document.getElementById("root"));
結(jié)合history,react-router一共有3中不同的router:
BrowserRouter通過history/createBrowserHistory引入:當切換時,url會動態(tài)更新,底層使用的時html5的pushState。
HashRouter通過history/createHashHistory引入:當切換時,動態(tài)修改hash,利用hashchange事件。
MemoryRouter 通過history/createMemoryHistory引入:將路徑,路由相關(guān)數(shù)據(jù)存入內(nèi)存中,不涉及url相關(guān)更新,兼容性好。
更多配置可以參考這里
4.如果想要在代碼邏輯中獲取當前的route路徑需要引入router-reducer:
新建main.js:
import { combineReducers } from "redux"; import { routerReducer } from "react-router-redux"; import todoReducer from "./todoReducer.js"; const reducers = combineReducers({ todoReducer, router: routerReducer }); export default reducers;
修改store.js:
import { createStore } from "redux"; import mainReducer from "./reducers/main.js"; const store = createStore(mainReducer); export default store;
然后就可以在this.props.router里面獲取單相關(guān)的路徑信息
5.如果需要自己通過action來觸發(fā)router的跳轉(zhuǎn),需要引入routerMiddleware:
import { createStore,applyMiddleware } from "redux"; import { routerMiddleware } from "react-router-redux"; const middleware = routerMiddleware(history); const store = createStore(mainReducer,applyMiddleware(middleware));
6.使用Route和Link和withRouter:
先說說都是干嘛的:
export default withRouter(connect( state => ({ todoList: state.todoReducer.todoList }) )(Main));
如果你在使用hash時遇到Warning: Hash history cannot PUSH the same path; a new entry will not be added to the history stack錯誤,可以將push改為replace即:
切換到2號
7.設(shè)置初始化路由:
BrowserRouter和HashRouter:
const history = createHistory(); history.push("2");
MemoryRouter:
const history = createMemoryHistory({ initialEntries: ["/2"] });使用redux-thunk
redux-thunk 是一個比較流行的 redux 異步 action 中間件,比如 action 中有 setTimeout 或者通過 fetch通用遠程 API 這些場景,那么久應(yīng)該使用 redux-thunk 了。redux-thunk 幫助你統(tǒng)一了異步和同步 action 的調(diào)用方式,把異步過程放在 action 級別解決,對 component 沒有影響。
1.安裝redux-thunk:
npm install redux-thunk --save
2.修改store.js:
import { createStore,applyMiddleware } from "redux"; import thunk from "redux-thunk"; import mainReducer from "./reducers/main"; ... const store = createStore(mainReducer, applyMiddleware(thunk)); ... export default store;
3.在action.js使用redux-thunk:
export const getData = (obj) => (dispatch, getState) => { setTimeout(()=>{ dispatch({ type: GET_DATA, obj: obj }); },1000); };使用axios和async/await
axios 是一個基于Promise 用于瀏覽器和 nodejs 的 HTTP 客戶端:
從瀏覽器中創(chuàng)建 XMLHttpRequest
從 node.js 發(fā)出 http 請求
支持 Promise API
自動轉(zhuǎn)換JSON數(shù)據(jù)
1.安裝axios:
npm install axios --save
2.在action中使用axios:
import axios from "axios"; export const getData = (obj) => (dispatch, getState) => { axios.get("/json/comments.json").then((resp)=>{ dispatch({ type: GET_DATA, obj: resp }); }); };
async/await:
Javascript的回調(diào)地獄,相信很多人都知道,尤其是在node端,近些年比較流行的是Promise的解決方案,但是隨著 Node 7 的發(fā)布,編程終級解決方案的 async/await應(yīng)聲而出。
function resolveAfter2Seconds() { return new Promise(resolve => { setTimeout(() => { resolve("resolved"); }, 2000); }); } async function asyncCall() { var result = await resolveAfter2Seconds(); } asyncCall();
async/await的用途是簡化使用 promises 異步調(diào)用的操作,并對一組 Promises執(zhí)行某些操作。await前提是方法返回的是一個Promise對象,正如Promises類似于結(jié)構(gòu)化回調(diào),async/await類似于組合生成器和 promises。
1.async/await需要安裝babel-plugin-transform-async-to-generator。
npm install babel-plugin-transform-async-to-generator --save
2.在.babelrc中增加配置:
"plugins": [ "transform-async-to-generator" ]
這樣做僅僅是將async轉(zhuǎn)換generator,如果你當前的瀏覽器不支持generator,你將會收到一個Uncaught ReferenceError: regeneratorRuntime is not defined的錯誤,你需要:
3.安裝babel-plugin-transform-runtime:
npm install babel-plugin-transform-async-to-generator --save
4.修改.babelrc中的配置(可以去掉之前配置的transform-async-to-generator):
"plugins": [ "transform-runtime" ]
5.如果不想引入所有的polyfill(參考上面對babel的解釋),可以增加配置:
"plugins": [ "transform-runtime", { "polyfill": false, "regenerator": true, } ]
6.結(jié)合axios使用
import axios from "axios"; export const getData = (obj) => async (dispatch, getState) => { let resp = axios.get("/json/comments.json"); dispatch({ type: GET_DATA, obj: resp }); };Code Splitting
1.對于webpack1,2之前,你可以使用require.ensure來控制一個組件的懶加載:
require.ensure([], _require => { let Component = _require("./Component.jsx"); },"lazyname")
2.在webpack4中,官方已經(jīng)不再推薦使用require.ensure來使用懶加載功能Dynamic Imports,取而代之的是ES6的import()方法:
import( /* webpackChunkName: "my-chunk-name" */ /* webpackMode: "lazy" */ "module" );
不小小看注釋里的代碼,webpack在打包時會動態(tài)識別這里的代碼來做相關(guān)的配置,例如chunk name等等。
3.Prefetching/Preloading modules:
webpack 4.6.0+支持了Prefetching/Preloading的寫法:
import(/* webpackPreload: true */ "ChartingLibrary");
3.結(jié)合React-Router使用:
react-loadable對上述的功能做了封裝,豐富了一些功能,結(jié)合React-Router起來使用更加方便。
npm install react-loadable --save
在react-router里使用:
function Loading() { return使用CommonsChunkPluginLoading...; } let Div2 = Loadable({ loader: () => import("./Div2"), loading: Loading, });
CommonsChunkPlugin 插件,是一個可選的用于建立一個獨立文件(又稱作 chunk)的功能,這個文件包括多個入口 chunk 的公共模塊。通過將公共模塊拆出來,最終合成的文件能夠在最開始的時候加載一次,便存起來到緩存中供后續(xù)使用。
1.在webpack4之前的用法:
new webpack.optimize.CommonsChunkPlugin({ name: "common", chunks: ["page1","page2"], minChunks: 3 })
name: string: 提出出的名稱
chunks: string[]: webpack會從傳入的chunk里面提取公共代碼,默認從所有entry里提取
minChunks: number|infinity|function(module,count)->boolean: 如果傳入數(shù)字或infinity(默認值為3),就是告訴webpack,只有當模塊重復(fù)的次數(shù)大于等于該數(shù)字時,這個模塊才會被提取出來。當傳入為函數(shù)時,所有符合條件的chunk中的模塊都會被傳入該函數(shù)做計算,返回true的模塊會被提取到目標chunk。
更多的參數(shù)配置,可以參考這里
2.在webpack4之后的用法:
module.exports = { //... optimization: { splitChunks: { chunks: "async", minSize: 30000, minChunks: 1, maxAsyncRequests: 5, maxInitialRequests: 3, automaticNameDelimiter: "~", name: true, cacheGroups: { vendors: { test: /[/]node_modules[/]/, priority: -10 }, default: { minChunks: 2, priority: -20, reuseExistingChunk: true } } } } };
splitChunks: 配置一個分離chunk(代替老版本的CommonsChunkPlugin)
cacheGroups: 自定義配置主要使用它來決定生成的文件:
test: 限制范圍
name: 生成文件名
priority: 優(yōu)先級
minSize: number: 最小尺寸必須大于此值,默認30000B
minChunks: 其他entry引用次數(shù)大于此值,默認1
maxInitialRequests: entry文件請求的chunks不應(yīng)該超過此值(請求過多,耗時)
maxAsyncRequests: 異步請求的chunks不應(yīng)該超過此值
automaticNameDelimiter: 自動命名連接符
chunks: 值為”initial”, “async”(默認) 或 “all”:
initial: 入口chunk,對于異步導(dǎo)入的文件不處理
async: 異步chunk,只對異步導(dǎo)入的文件處理
all: 全部chunk
你的點贊是我持續(xù)分享好東西的動力,歡迎點贊!
交流干貨系列文章匯總?cè)缦拢X得不錯點個Star,歡迎 加群 互相學(xué)習(xí)。
https://github.com/qq44924588...
我是小智,公眾號「大遷世界」作者,對前端技術(shù)保持學(xué)習(xí)愛好者。我會經(jīng)常分享自己所學(xué)所看的干貨,在進階的路上,共勉!
關(guān)注公眾號,后臺回復(fù)福利,即可看到福利,你懂的。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/108654.html
摘要:哪吒別人的看法都是狗屁,你是誰只有你自己說了才算,這是爹教我的道理。哪吒去他個鳥命我命由我,不由天是魔是仙,我自己決定哪吒白白搭上一條人命,你傻不傻敖丙不傻誰和你做朋友太乙真人人是否能夠改變命運,我不曉得。我只曉得,不認命是哪吒的命。 showImg(https://segmentfault.com/img/bVbwiGL?w=900&h=378); 出處 查看github最新的Vue...
摘要:前言本文基于,主要涉及基本概念基本配置和實際項目打包優(yōu)化。關(guān)于概念方面參考官網(wǎng),常用配置來自于網(wǎng)絡(luò)資源,在文末有相關(guān)參考鏈接,實踐部分基于自己的項目進行優(yōu)化配置。同一文件中,修改某個影響其他。 前言:本文基于weboack4.x,主要涉及webpack4 基本概念、基本配置和實際項目打包優(yōu)化。關(guān)于概念方面參考官網(wǎng),常用配置來自于網(wǎng)絡(luò)資源,在文末有相關(guān)參考鏈接,實踐部分基于自己的項目進行...
摘要:五六月份推薦集合查看最新的請點擊集前端最近很火的框架資源定時更新,歡迎一下。蘇幕遮燎沈香宋周邦彥燎沈香,消溽暑。鳥雀呼晴,侵曉窺檐語。葉上初陽乾宿雨,水面清圓,一一風(fēng)荷舉。家住吳門,久作長安旅。五月漁郎相憶否。小楫輕舟,夢入芙蓉浦。 五、六月份推薦集合 查看github最新的Vue weekly;請::點擊::集web前端最近很火的vue2框架資源;定時更新,歡迎 Star 一下。 蘇...
摘要:五六月份推薦集合查看最新的請點擊集前端最近很火的框架資源定時更新,歡迎一下。蘇幕遮燎沈香宋周邦彥燎沈香,消溽暑。鳥雀呼晴,侵曉窺檐語。葉上初陽乾宿雨,水面清圓,一一風(fēng)荷舉。家住吳門,久作長安旅。五月漁郎相憶否。小楫輕舟,夢入芙蓉浦。 五、六月份推薦集合 查看github最新的Vue weekly;請::點擊::集web前端最近很火的vue2框架資源;定時更新,歡迎 Star 一下。 蘇...
閱讀 2574·2021-10-19 11:41
閱讀 2414·2021-09-01 10:32
閱讀 3376·2019-08-29 15:21
閱讀 1754·2019-08-29 12:20
閱讀 1161·2019-08-29 12:13
閱讀 599·2019-08-26 12:24
閱讀 2519·2019-08-26 10:26
閱讀 827·2019-08-23 18:40