使用 webpack 從零搭建 react項目的git地址:https://github.com/YueJingGe/webpack-react/tree/master
初始化 npm
yarn init
安裝 webpack
yarn add webpack -D
安裝 webpack-cli
yarn add webpack-cli -D
如果你使用 webpack v4+ 版本,你還需要安裝 CLI。
此工具用於在命令行中運行 webpack。
比如:npx webpack (以 src/index.js 作爲入口起點,生成 dist/main.js 作爲輸出)
npx 命令:可以運行 package 中的 webpack 二進制文件 即:./node_modules/.bin/webpack 文件
初始化 index.html、index.js 文件
使用一個配置文件 webpack.config.js
比 CLI 更強大,更靈活
npx webpack = npx webpack --config webpack.config.js = npm run build
入口
出口
管理資源
- CSS / LESS / 提取(不重要)
style-loader css-loader less-loader - 圖片
file-loder image-webpack-loader(圖片壓縮,很必要)
管理輸出
- html-webpack-plugin 自動生成 index.html 文件
- clean-webpack-plugin 構建之前清理 dist 文件
開發環境
-
mode
-
使用 Source Map
一般情況下,設置了 mode 之後 Source Map 就不需要設置了
-
觀察模式
可以自動編譯,但是需要手動刷新瀏覽器
webpack-dev-server
1.實時重新加載頁面;2.將 dist 目錄下的文件 serve 到 localhost:8080 下;3.瀏覽器自動加載頁面
模塊熱替換
-
webpack.HotModuleReplacementPlugin
它允許在運行時更新所有類型的模塊,而無需完全刷新
minification(代碼壓縮) 和 tree shaking
通過設置 mode 爲 production 來啓動代碼壓縮和 tree shaking(刪除未引用的代碼)
配置環境
development(開發環境) 和 production(生產環境) 這兩個環境下的構建目標存在着巨大差異。
在開發環境中,我們需要:強大的 source map 和一個有着 live reloading(實時重新加載) 或 hot module replacement(熱模塊替換) 能力的 localhost server。
而生產環境目標則轉移至其他方面,關注點在於壓縮 bundle、更輕量的 source map、資源優化等,
通過這些優化方式改善加載時間。
代碼分離
-
防止重複 splitChunks
將公共的依賴模塊提取出來,爲頁面間共享的應用程序代碼創建 bundle
-
動態導入 chunkFilename
const { default: _ } = await import( /* webpackChunkName: "lodash" */ "lodash" );
緩存
-
輸出文件名 [name].[hash].js
-
提取引導模板 runtimeChunk
將 runtime 代碼分離到一個單獨的 chunk 中
-
提取第三方庫 cacheGroups
例如 lodash 或 react 提取到單獨的 vendor chunk 文件中
模塊標識符 HashedModuleIdsPlugin
沒有效果。。❌ (忽略)
性能
-
對最少數量的模塊使用 loader
include / exclude
公共路徑 publicPath
暫時還不知道什麼用途?!
外部擴展 externals
暫時可以不使用
react
安裝 react、react-dom
解析 jsx babel-loader
{
test: /\.m?js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: "babel-loader",
options: {
presets: ["@babel/preset-react"] // 重要
}
}
}
配置路由 react-router-dom
具體參考官網:https://reacttraining.com/react-router/ 進行配置
注意路由的寫法 ‘/home/’ 這裏最後的 ‘/’ 記得去掉,不要帶上,否則會出錯。
-
解決 BrowserRouter 刷新 404問題
historyApiFallback: true
-
配置路由按需加載 react-loadable
-
解決動態導入的問題 @babel/plugin-syntax-dynamic-import
報錯:Support for the experimental syntax ‘dynamicImport’ isn’t currently enabled (8:17)
{
test: /\.m?js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: "babel-loader",
options: {
presets: ["@babel/preset-react"],
plugins: ["@babel/plugin-syntax-dynamic-import"] // 重點在此
}
}
}
配置組件
-
按需加載 babel-plugin-import
優點:只需從 antd 引入模塊即可,無需單獨引入樣式;babel-plugin-import 會幫助你加載 JS 和 CSS
-
引入antd 按需加載之後報錯 .bezierEasingMixin(); ^ Inline JavaScript is not enabled.
如果使用的 webpack 那就在 webpack 的配置中找到 less 的配置,在選項中添加 javascriptEnabled: true
-
定製主題 使用 less 提供的 modifyVars 的方式進行覆蓋變量
webpack+react+router+redux項目配置中遇到的問題
解決 eslintrc import 報錯
問題:Parsing error: The keyword 'import' is reserved
方案:.eslintrc
文件中配置 "parser": "babel-eslint"
解決 eslintrc html 報錯
解決方案:
第一步: npm install --save-dev eslint-plugin-html
第二步: .eslintrc
文件中配置 "plugins": ["html"]
jsx語法報錯
index.js 文件
import React from "react";
import ReactDom from "react-dom";
ReactDom.render(<div>hello,react</div>, document.getElementById("root"));
報錯信息:
[WDS] Errors while compiling. Reload prevented.
Module parse failed: Unexpected token (5:2)
You may need an appropriate loader to handle this file type.
|
| ReactDom.render(
> <div>hello,react</div>,
| document.getElementById("root")
| );
原因:無法支持 jsx 語法,您可能需要適當的加載程序來處理此文件類型。
解決:
第一步:安裝加載程序
npm install -D @babel/core babel-loader @babel/preset-env @babel/preset-react
第二步:在 webpack 中配置
module: {
rules: [
{
test: /\.m?js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: "babel-loader",
options: {
presets: ["@babel/preset-react", "@babel/preset-env"]
}
}
}
];
}
Uncaught Invariant Violation: Target container is not a DOM element.
解決:在 webpack 中配置
plugins: [
new HtmlWebpackPlugin({
title: "從零搭建webpack-react",
template: "src/assets/index.html" // webpack需要模板的路徑
})
];
browserHistory 刷新頁面 404
報錯:Cannot GET /todo
解決:webpack 中配置historyApiFallback: true
devServer: {
historyApiFallback: true;
}
import 編譯 less 失敗報錯
報錯信息:
ERROR in ./src/components/Todo/index.less 1:0
Module parse failed: Unexpected token (1:0)
You may need an appropriate loader to handle this file type.
> .todo-container{
| width: 100%;
| }
@ ./src/components/Todo/index.js 20:0-22
@ ./src/App.js
@ ./src/index.js
解決:
module: {
rules: [
{
test: /\.(css|less)$/,
use: ["style-loader", "css-loader", "less-loader"]
}
];
}
報錯‘less’找不到
報錯信息:
Module build failed (from ./node_modules/less-loader/dist/cjs.js):
Error: Cannot find module 'less'
原因: less-loader
對 less
有依賴
解決:安裝 less
報錯 syntax ‘classProperties’ isn’t currently enabled
解決:安裝插件:
npm install --save-dev @babel/plugin-proposal-class-properties
此插件轉換靜態類屬性以及使用屬性初始化程序語法聲明的屬性。
.babelrc 文件中配置:
{
"plugins": ["@babel/plugin-proposal-class-properties"]
}
使用es6類屬性時,eslint報Parsing error: Unexpected token =
報錯場景:
onPressEnter = e => {
console.log(e.target.value);
};
解決:
第一步: npm install eslint babel-eslint --save-dev
第二步:.eslintrc文件中配置 "parser": "babel-eslint"