從零搭建webpack+react+router+redux項目踩坑之旅

使用 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-loaderless 有依賴

解決:安裝 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"

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章