上一篇前端基础-一步步搭建webpack4(react篇)中,已经成功搭建了一个能运行起来的react项目。这一篇咱们来学习新的东西。javascript
在咱们正式工做中,前端项目分为:正式环境(production
)、测试环境(development
),在webpack4中,直接使用 mode(环境)
就能够了,production
:生产模式,打包的代码会被压缩,不开启代码调试,development
:开发模式,打包的代码不会被压缩,开启代码调试。html
那么咱们先来讲说development
开发模式,在咱们使用开发模式的时候,会搭配热更新一块儿来使用。可是webpack-dev-server
的hot
,在更新时,会刷新整个页面。在react开发时,刷新了页面,会丢失之前的数据流,须要咱们从新再去操做。这样很麻烦。因此咱们就须要一个新的插件,react-hot-loader
,react-hot-loader
不会刷新整个页面,它只是替换了修改的代码,作到了页面的局部刷新。前端
那么咱们先来使用一下react-hot-loader
java
首先,安装一下react-hot-loadernode
yarn add react-hot-loader -D
react
使用方法很简单。首先在.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
就已经生成了生产环境所对应的代码了。