前端基礎-一步步搭建webpack4(react篇 )二

開場

上一篇前端基礎-一步步搭建webpack4(react篇)中,已經成功搭建了一個能運行起來的react項目。這一篇咱們來學習新的東西。javascript

正片

在咱們正式工做中,前端項目分爲:正式環境(production)、測試環境(development),在webpack4中,直接使用 mode(環境)就能夠了,production:生產模式,打包的代碼會被壓縮,不開啓代碼調試,development:開發模式,打包的代碼不會被壓縮,開啓代碼調試。html

那麼咱們先來講說development開發模式,在咱們使用開發模式的時候,會搭配熱更新一塊兒來使用。可是webpack-dev-serverhot,在更新時,會刷新整個頁面。在react開發時,刷新了頁面,會丟失之前的數據流,須要咱們從新再去操做。這樣很麻煩。因此咱們就須要一個新的插件,react-hot-loaderreact-hot-loader不會刷新整個頁面,它只是替換了修改的代碼,作到了頁面的局部刷新。前端

那麼咱們先來使用一下react-hot-loaderjava

react-hot-loader

首先,安裝一下react-hot-loadernode

yarn add react-hot-loader -Dreact

使用方法很簡單。首先在.babelrc中添加一個pluginswebpack

// .babelrc
"plugins" : [ "react-hot-loader/babel" ]
複製代碼

以後在webpack.config.js中entry中添加一行'react-hot-loader/patch',而後在plugins中開啓HMR(熱替換功能,替換更新部分,不重載頁面)web

// webpack.config.js
// entry
entry : [ "react-hot-loader/patch" , "./src/index.js" ]
// plugins 添加
plugins : [
    new webpack.HotModuleReplacementPlugin(),
    // ....其餘的plugins
]
複製代碼

接下來,咱們須要修改一下index.js。正則表達式

// src/index.js
import React from "react";
import ReactDom from "react-dom";
import { AppContainer } from "react-hot-loader";
import App from "./App";

// 初始化
renderWithHotReload(App);

// 熱更新
if (module.hot) {
  module.hot.accept("./App.js", function() {
    const NextApp = require("./App.js").default;
    renderWithHotReload(NextApp);
  });
}

function renderWithHotReload(Index) {
  ReactDom.render(
    <AppContainer> <Index /> </AppContainer>,
    document.getElementById("app")
  );
}
複製代碼

module.hot:若是已經經過HotModuleReplacementPlugin啓用了模塊熱替換(Hot Module Replacement),則它的接口將被暴露在module.hot屬性下面。一般,用戶先要檢查這個接口是否可訪問,而後再開始使用它。 module.hot.accept:接受給定依賴模塊的更新,並觸發一個回掉函數來對這些更新做出相應npm

由於使用了JavaScript中新的特性,全部須要安裝下@babel/plugin-proposal-class-properties,來支持一下這些特性。

安裝成功後,咱們在.babelrc中添加plugins

// .babelrc
"plugins": [
    "react-hot-loader/babel",
    "@babel/plugin-proposal-class-properties"
  ]
複製代碼

好了,一切準備就緒了,咱們如今來修改下src/App.js,來檢查一下,react-hot-loader是否已經啓用,是否達到了咱們要的效果

import React from "react";
class App extends React.Component {
  state = {
    num: 0
  };
  changeNum = () => {
    this.setState({
      num: this.state.num + 1
    });
  };

  render() {
    const { num } = this.state;
    return (
      <div> {num} <button onClick={this.changeNum}>add num</button> </div>
    );
  }
}

export default App;
複製代碼

當咱們按下add num時,num改變成了1,而後修改add num爲add num 1。num的值仍是爲1。因此證實了react-hot-loader成功了。

生產環境,開發環境的配置

好了。接下來,在咱們正式開發的狀況,咱們是要分爲正式環境和開發環境的。通常咱們的命令爲

npm run dev 開發環境,有react-hot-loader功能、debug等等的測試、斷點的功能

npm run build 正式環境,打包一份文件夾,上傳到服務器。這裏是沒有測試、斷點之類的功能的。

那咱們就來寫一下區分環境的代碼吧

首先咱們須要建立三個文件,config/webpack.commom.js config/webpack.development.js config/webpack.production.js

接下來咱們安裝一下咱們須要的包webpack-merge yarn add webpack-merge 這是用來合併webpack配置的。咱們須要一個公共的webpack.js方法,存放的是development和production公共的配置。而後使用webpack-merge合併。

接下來看一下,config/webpack.common.js裏的代碼吧

const path = require("path");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
  entry: ["./src/index.js"],
  output: {
    path: path.resolve(__dirname, "../dist"),
    filename: "bundle.js"
  },
  resolve: {
    extensions: [".js", ".jsx"]
  },
  module: {
    rules: [
      // 也就是之前的loader
      {
        test: /\.jsx?$/, // 正則表達式,匹配編譯的文件
        exclude: /node_modules/, // 排除特定條件,如一般會寫node_modules,即把某些目錄/文件過濾掉
        use: [
          {
            loader: "babel-loader" // loader 必須要有它,它至關因而一個test匹配到的文件對應的解析起,babel-loader、style-loader、sass-loader等等
          }
        ]
      }
    ]
  },
  plugins: [
    new CleanWebpackPlugin(),
    new HtmlWebpackPlugin({
      filename: "index.html", // 最終生成的文件名
      template: path.join(__dirname, "..", "index.html")
    })
  ],
  performance: false // 關閉性能提示
};
複製代碼

接下來咱們先把前面寫好的帶有react-hot-loader的webpack提煉一些代碼到config/webpack.development.js

// config/webpack.development.js
const path = require("path");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
  entry: ["./src/index.js"],
  output: {
    path: path.resolve(__dirname, "../dist"),
    filename: "bundle.js"
  },
  resolve: {
    extensions: [".js", ".jsx"]
  },
  module: {
    rules: [
      // 也就是之前的loader
      {
        test: /\.jsx?$/, // 正則表達式,匹配編譯的文件
        exclude: /node_modules/, // 排除特定條件,如一般會寫node_modules,即把某些目錄/文件過濾掉
        use: [
          {
            loader: "babel-loader" // loader 必須要有它,它至關因而一個test匹配到的文件對應的解析起,babel-loader、style-loader、sass-loader等等
          }
        ]
      }
    ]
  },
  plugins: [
    new CleanWebpackPlugin(),
    new HtmlWebpackPlugin({
      filename: "index.html", // 最終生成的文件名
      template: path.join(__dirname, "..", "index.html")
    })
  ],
  performance: false // 關閉性能提示
};
複製代碼

咱們把package.json中的script中的代碼改動一下

"dev": "webpack-dev-server --config ./config/webpack.develop.js --color --propgress",
複製代碼

這樣咱們運行npm run dev,就能夠啓動項目了

咱們接下來在webpack.production.js中添加一下打包的代碼。

// config/webpack.production.js
const path = require("path");
const webpack = require("webpack");
const merge = require("webpack-merge");
const commonConfig = require("./webpack.common");

module.exports = merge(commonConfig, {
  mode: "production",
  output: {
    path: path.resolve(__dirname, "../dist"),
    filename: "js/[name].js",
    chunkFilename: "js/[name].[chunkhash:8].js"
  },
  devtool: "cheap-module-source-map",
  optimization: {
    splitChunks: {
      chunks: "all", // 全部的 chunks 代碼公共的部分分離出來成爲一個單獨的文件
      cacheGroups: {
        // 公共代碼打包分組配置
        vvendors: {
          test: "/[\\/]node_modules[\\/]/",
          name: "vendors"
        }
      }
    }
  }
});
複製代碼

咱們在package.json中的script中的添加一行

"build": "webpack --config ./config/webpack.production.js --color --propgress"
複製代碼

如今咱們運行npm run build就已經生成了生產環境所對應的代碼了。

相關文章
相關標籤/搜索