This article describes how to build a React scaffolding from scratch, including how to add Redux and the React Router environment.
This article code address:react-mobx-starter.
It is recommended that you pull down the code and view it together with this article for better results.
Code download command:
git clone -b example https://github.com/beichensky/react-mobx-starter.git
Copy the code
The Babel configuration in scaffolding was recently updated to version 7.0.0, so some changes have been made. The current versions of various libraries in scaffolding are as follows:
- Node: 10.15.3
- NPM: 6.4.1
- Webpack: 4.29.6
- Webpack – cli: 3.3.0
- Webpack dev – server: 3.1.4
- @ Babel/core: 7.0.0
- React: 16.8.6
- Mobx: 5.9.4
- The react – the router – dom: 5.0.0
If you are upgrading from a lower version to 7.0.0, there is a new command that can directly help you update the project:
npx babel-upgrade --write --install
Copy the code
More information about Babel-upgrade can be found in the official instructions.
Previously on
The Demo in this article is divided into two environments, one for development and the other for production.
-
Development environment is about how to configure a better, more convenient development environment;
-
Production is about configuring a more optimized, smaller version of the production environment.
I’ve written several articles on the use of Webpack before, and this article builds on Webpack and expands on previous code.
-
The development environment configuration is an extension of the Webpack development environment configuration from scratch (with Demo).
-
Production environment configuration is an extension of the production environment configuration using Webpack (with Demo) article.
Suggestion: for friends who do not know Webpack, you can first look at the two articles: build a Webpack development environment configuration from scratch (with Demo) and use Webpack for production environment configuration (with Demo), you can better start with this article.
Although this article is an extension of the previous article, it will go through the configuration of each step in detail.
Create a project structure
Create a folder named react-Mox-Starter
mkdir react-mobx-starter
Copy the code
Initialize the package.json file
cd react-mobx-starter
# Generate the default package.json file directly
npm init -y
Copy the code
We’re going to create a SRC directory to hold the code that we’re writing and we’re going to create a public directory to hold the public files and we’re going to create a Webpack directory to hold the WebPack configuration files
mkdir src
mkdir public
mkdir webpack
Copy the code
Create a Pages folder in the SRC directory for your written page components. Create a Components folder for your public components. Create a utils folder for your common utility classes
cd src
mkdir pages
mkdir components
mkdir utils
Copy the code
Create an index. HTML file in the public directory. Create an index.js file in the SRC directory. Create webpack.config.dev.js and webpack.config.prod.js in the webpack directory
webpack.config.dev.js
Used to write the WebPack development environment configurationwebpack.config.prod.js
Used to write the WebPack production environment configuration
index.html
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="Width = device - width, initial - scale = 1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>React + Mobx family bucket scaffolding</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
Copy the code
index.js
function createElement() {
const ele = document.createElement('div');
ele.innerHTML = 'Hello, React';
const root = document.querySelector('#root');
root.appendChild(ele);
}
createElement();
Copy the code
Webpack.config.dev. js and webpack.config.prod.js are not written at this point, but we’ll cover them in more detail later.
Let’s take a look at the project structure at this point, and then we can configure WebPack.
├─ ├─ exercises, ├─ exercises, exercises, exercises, exercises, exercises, exercises, exercises Webpack. Config. Dev. Js └ ─ webpack. Config. Prod. Js ├ ─ package. The jsonCopy the code
Configure the React development environment
Add an execution script to the package.json file to execute the webpack command:
{
...,
"scripts": {
"start": "webpack --config webpack/webpack.config.dev.js"
},
...
}
Copy the code
Install webPack-related plug-ins
Install Webpack and WebPack-CLI
npm install webpack webpack-cli --save-dev
Copy the code
Entrance and exit
When configuring a project using WebPack, there must be an entry and an exit, as module entry and project output.
webpack.config.dev.js
const path = require('path');
const appSrc = path.resolve(__dirname, '.. /src');
const appDist = path.resolve(__dirname, '.. /dist');
const appPublic = path.resolve(__dirname, '.. /public');
const appIndex = path.resolve(appSrc, 'index.js');
module.exports = {
entry: appIndex,
output: {
filename: 'public/js/[name].[hash:8].js'.path: appDist,
publicPath: '/'}}Copy the code
Add htML-webpack-plugin
Dist /public/js file, but this file is named by the hash value. It is too much trouble to manually import it into the index.html file each time. So the HTML-webpack-plugin can be introduced.
The HTML-webpack-plugin serves two purposes
- Can be
public
Copy the folder under the directory todist
Output folder - Can automatically
dist
Under thejs
File import intohtml
In the file
The installationhtml-webpack-plugin
The plug-in
npm install html-webpack-plugin --save-dev
Copy the code
usehtml-webpack-plugin
The plug-in
webpack.config.dev.js
const path = require('path');
+ const HTMLWebpackPlugin = require('html-webpack-plugin');
const appSrc = path.resolve(__dirname, '.. /src');
const appDist = path.resolve(__dirname, '.. /dist');
const appPublic = path.resolve(__dirname, '.. /public');
const appIndex = path.resolve(appSrc, 'index.js');
+ const appHtml = path.resolve(appPublic, 'index.html');
module.exports = {
entry: appIndex,
output: {
filename: 'public/js/[name].[hash:8].js'.path: appDist,
publicPath: '/'
},
+ plugins: [
+ new HTMLWebpackPlugin({
+ template: appHtml,
+ filename: 'index.html'+}) +]}Copy the code
Setting development Mode
The mode property in the Webpack configuration can be set to ‘development’ and ‘production’. We are currently in the development environment configuration, so it can be set to ‘development’.
webpack.config.dev.js
. module.exports = { + mode:'development'. }Copy the code
Set the devtool
In order to quickly locate the error in the project, you can set devtool to generate the resource map. We use inline-source-map here. For more options, see the difference here.
webpack.config.dev.js
. module.exports = {mode: 'development',
+ devtool: 'inline-source-map'. }Copy the code
Start the project service with webpack-dev-server
Webpack – dev – server installation
npm install webpack-dev-server --save-dev
Copy the code
Configuration webpack – dev – server
webpack.config.dev.js
. module.exports = {mode: 'development'.devtool: 'inline-source-map',
+ devServer: {
+ contentBase: appPublic,
+ hot: true,
+ host: 'localhost',
+ port: 8000,
+ historyApiFallback: true,
+ // Whether to display errors in the browser mask
+ overlay: true,
+ inline: true,
+ // Prints information
+ stats: 'errors-only',
+ // Set the proxy
+ proxy: {
+ '/api': {
+ changeOrigin: true,
+ target: 'https://easy-mock.com/mock/5c2dc9665cfaa5209116fa40/example',
+ pathRewrite: {
+ '^/api/': '/'+} +} +} +},... }Copy the code
Modify the start script in package.json:
{
...,
"scripts": {
"start": "webpack-dev-server --config webpack/webpack.config.dev.js"
},
...
}
Copy the code
Use the friendly-errors-webpack-plugin
The friendly-errors-webpack-plugin can display better prompt functionality on the command line.
Install the friendly – errors – webpack – the plugin:
npm install friendly-errors-webpack-plugin --save-dev
Copy the code
Use friendly – errors – webpack – the plugin:
webpack.config.dev.js
const path = require('path');
const HTMLWebpackPlugin = require('html-webpack-plugin');
+ const FriendlyErrorsWebpackPlugin = require('friendly-errors-webpack-plugin'); . module.exports = { ... plugins: [new HTMLWebpackPlugin({
template: appHtml,
filename: 'index.html'+})new FriendlyErrorsWebpackPlugin(),
]
}
Copy the code
Enabling hot loading
webpack.config.dev.js
const path = require('path');
const HTMLWebpackPlugin = require('html-webpack-plugin');
const FriendlyErrorsWebpackPlugin = require('friendly-errors-webpack-plugin');
+ const webpack = require('webpack'); . module.exports = { ... plugins: [ ... new FriendlyErrorsWebpackPlugin(), +new webpack.HotModuleReplacementPlugin()
]
}
Copy the code
Run the project and test the configuration
Run the NPM run start command. After a success message is displayed, open http://localhost:8000 and see Hello React.
Configure the Babel
Now we have less code in index.js, so no problem. However, if I want to use some ES6 syntax or JS features that are not yet defined by the standard, then I need to use Babel for conversion. Let’s configure Babel.
Install the Babel plug-in
npm install @babel/core babel-loader --save-dev
Copy the code
Use the Babel – loader
Sets the cacheDirectory property to be used to cache loader execution results. Subsequent WebPack builds will attempt to read the cache to avoid the potentially high-performance Babel recompilation process that can occur each time it is executed.
webpack.config.dev.js
. module.exports = { ... plugins: [ ... ] .module: {
rules: [{test: /\.(js|jsx)$/.loader: 'babel-loader? cacheDirectory'.include: [ appSrc ],
exclude: /node_modules/}}}]Copy the code
Create a new babel.config.js file in the project root directory
The babel.config.js file is a runtime control file that automatically reads the Babel configuration in the babel.config.js file when the project is compiled.
Use Babel related Presets
Install related plug-ins:
@babel/preset-env
: You can use all of them in a projectECMAScript
The latest features in the standard.@babel/preset-react
: Can be used in projectsreact
Syntax.
npm install babel-preset-env babel-preset-react --save-dev
Copy the code
To configure the babel.config.js file:
module.exports = (api) = > {
api.cache(true);
return {
presets: [
"@babel/preset-env"."@babel/preset-react"]}}Copy the code
Use Babel-related plugins
After Babel is upgraded to version 7.0.0, @babel/preset-stage-0 is deprecated and the plugin used needs to be installed itself. If you are upgrading from a lower version to 7.0.0, there is a new command that can directly help you update the project:
npx babel-upgrade --write --install
Copy the code
More information about Babel-upgrade can be found in the official instructions.
Install related plug-ins:
@babel/plugin-proposal-decorators
: Decorator syntax can be used in projects.@babel/plugin-proposal-class-properties
: You can use the new class attribute syntax in your project.@babel/plugin-transform-runtime
: Use this plug-in to directly use the code pairs in Babel-Runtimejs
Files are converted to avoid code redundancy.@babel/runtime-corejs2
: cooperate withbabel-plugin-transform-runtime
Plug-ins in pairs@babel/plugin-syntax-dynamic-import
: Can be used in projectsimport()
This syntax@babel/plugin-proposal-export-namespace-from
: Modules can be exported using the namespace export *@babel/plugin-proposal-throw-expressions
: You can throw an expression with an exception@babel/plugin-proposal-logical-assignment-operators
: Logical assignment operators can be used@babel/plugin-proposal-optional-chaining
Can you access deeply nested properties or functions using optional chains? .@babel/plugin-proposal-pipeline-operator
: you can use the pipeline operator | >@babel/plugin-proposal-nullish-coalescing-operator
Can use null value merge syntax?@babel/plugin-proposal-do-expressions
: You can use the DO expression (think of it as a more complex version of the ternary operator)@babel/plugin-proposal-function-bind
: You can use the function binding syntax obj::func
npm install @babel/plugin-proposal-decorators @babel/plugin-proposal-class-properties @babel/plugin-transform-runtime @babel/runtime-corejs2 @babel/plugin-syntax-dynamic-import @babel/plugin-proposal-export-namespace-from @babel/plugin-proposal-throw-expressions @babel/plugin-proposal-logical-assignment-operators @babel/plugin-proposal-optional-chaining @babel/plugin-proposal-pipeline-operator @babel/plugin-proposal-nullish-coalescing-operator @babel/plugin-proposal-do-expressions @babel/plugin-proposal-function-bind --save-dev
Copy the code
To configure the babel.config.js file:
module.exports = (api) = > {
api.cache(true);
return {
presets: [
"@babel/preset-env"."@babel/preset-react"].plugins: [["@babel/plugin-proposal-decorators",
{
"legacy": true}], ["@babel/plugin-transform-runtime",
{
"corejs": 2}], ["@babel/plugin-proposal-class-properties",
{
"loose": true}]."@babel/plugin-syntax-dynamic-import".// Modules can be exported using the namespace export *
"@babel/plugin-proposal-export-namespace-from".// You can throw an expression with an exception,
"@babel/plugin-proposal-throw-expressions".// Export by default
"@babel/plugin-proposal-export-default-from".// Logical assignment operators can be used
"@babel/plugin-proposal-logical-assignment-operators".// Can you access deeply nested properties or functions using an optional chain? .
"@babel/plugin-proposal-optional-chaining"./ / you can use the pipeline operator | >
[
"@babel/plugin-proposal-pipeline-operator",
{
"proposal": "minimal"}].// Can use null value merge syntax??
"@babel/plugin-proposal-nullish-coalescing-operator".// You can use the do expression (think of it as a complicated version of the ternary operator)
"@babel/plugin-proposal-do-expressions".// You can use the function binding syntax obj::func
"@babel/plugin-proposal-function-bind"]}}Copy the code
Note the order in which the @babel/plugin-proposal-decorators plugins are placed, preferably first, otherwise some annotations may fail.
At this point, the basic configuration for Babel is complete. Then we can use all the new JS features in our projects.
Add a LOADER related to the CSS
Js file related babel-loader is configured, but sometimes we want to add styles to elements in a project, and webpack considers everything to be a module, so we need other loaders to parse a wave of style code.
Install related plug-ins:
css-loader
: handlingcss
In the fileurl()
And so on.style-loader
Will:css
Inserted into the pagestyle
The label.less-loader
: is toless
File compiled intocss
.postcss-loader
: can integrate many plug-ins, used for operationcss
. We use it here for integrationautoprefixer
To automatically add prefixes.
npm install css-loader style-loader less less-loader postcss-loader autoprefixer --save-dev
Copy the code
Configure the style dependent Loader
- Due to the
React
Cannot be used directly similarVue
中scope
This local effect variable, so we can usewebpack
To provide theCSS Module
. 2, because it will be used laterantd
, so introducingantd
Need to be turned onless
的javascript
Choice, so you want to putless-loader
The properties in thejavascriptEnabled
Set totrue
.
Configure in webpack.config.dev.js:
. const autoprefixer =require('autoprefixer');
module.exports = { ... .plugins: [...]. .module: {
rules: [..., {test: /\.(css|less)$/.exclude: /node_modules/.use: [{
loader: 'style-loader'
},
{
loader: 'css-loader'.options: {
sourceMap: true.modules: true.localIdentName: '[local].[hash:8]'}}, {loader: 'postcss-loader'.options: {
plugins: (a)= > [autoprefixer()]
}
},
{
loader: 'less-loader'.options: {
javascriptEnabled: true}}]}, {test: /\.(css|less)$/.include: /node_modules/.use: [{
loader: 'style-loader'
},
{
loader: 'css-loader'.options: {}}, {loader: 'postcss-loader'.options: {
plugins: (a)= > [autoprefixer()]
}
},
{
loader: 'less-loader'.options: {
javascriptEnabled: true}}]},]}}Copy the code
Add other modules to parse loader configurations
Install related plug-ins:
npm install file-loader csv-loader xml-loader html-loader markdown-loader --save-dev
Copy the code
Configure in webpack.config.dev.js:
. module.exports = { ... .plugins: [...]. .module: {
rules: [...// Parse image resources
{
test: /\.(png|svg|jpg|gif)$/.use: [
'file-loader']},// Parse the font
{
test: /\.(woff|woff2|eot|ttf|otf)$/.use: [
'file-loader']},// Parse data resources
{
test: /\.(csv|tsv)$/.use: [
'csv-loader']},// Parse data resources
{
test: /\.xml$/.use: [
'xml-loader']},// Parse the MakeDown file
{
test: /\.md$/.use: [
'html-loader'.'markdown-loader'}]}}Copy the code
Additional WebPack configuration optimization
Add the Resolve Allias attribute and set the alias
The alias attribute in Resolve can be used to alias common folders. If the alias attribute in Resolve is used to alias common folders, the alias attribute in Resolve can be used to alias common folders
webpack.config.dev.js
...module.exports = { ... .plugins: [...]. .module: {... }, + resolve: { + alias: { + src: appSrc, + utils: path.resolve(__dirname,'.. /src/utils'),
+ pages: path.resolve(__dirname, '.. /src/pages'),
+ components: path.resolve(__dirname, '.. /src/components'+} +}}Copy the code
Add the resolve.modules attribute to specify where third-party modules will be stored
As we know, when searching for modules, node_modules in the current directory will be searched all the way to node_modules in the disk root directory. So to reduce the search steps, we can set the resolve.modules property to force only looking up modules from the project’s node_modules.
webpack.config.dev.js
...module.exports = { ... .plugins: [...]. .module: {... },resolve: {
...,
+ modules: [path.resolve(__dirname, '.. /node_modules')].}}Copy the code
Install React, MObx, and React Router plugins
npm install react react-dom prop-types mobx mobx-react react-router-dom --save
Copy the code
The introduction of antd
Follow the instructions on antD’s website to add the configuration directly to the babel.config.js file and then it will be used normally in the project.
Install antD plug-ins:
npm install antd moment --save
Copy the code
Install babel-plugin-import to load components on demand:
npm install babel-plugin-import --save-dev
Copy the code
Add antD configuration to babel.config.js:
module.exports = (api) = > {
api.cache(true);
return {
presets: [...]. .plugins: [..., + [+"import", + {+"libraryName": "antd",
+ "style": true+} +],... ] }Copy the code
React development
Basically all the necessary plug-ins have been introduced so it’s time to develop.
Modify the index.js file in the root directory
index.js
import React from 'react';
import ReactDom from 'react-dom';
import { Provider } from 'mobx-react'
import { LocaleProvider } from 'antd';
import { HashRouter } from 'react-router-dom';
import zh_CN from 'antd/lib/locale-provider/zh_CN';
import 'moment/locale/zh-cn';
import GlobalModel from './GlobalModel';
// import App from './App';
const globalModel = new GlobalModel();
const App = (a)= > {
return <div>The development environment is configured</div>
}
ReactDom.render(
<Provider globalModel={ globalModel} >
<LocaleProvider locale={zh_CN}>
<HashRouter>
<App />
</HashRouter>
</LocaleProvider>
</Provider>.document.querySelector('#root'));Copy the code
Run the NPM run start command and open http://localhost:8000/ in the browser. You can see that the configuration of the development environment is complete.
At this point, it shows that our various plug-ins and libraries have been introduced and can be used normally.
Use React Route to redirect routes between pages
Create app.js file in SRC directory:
App.js
import React from 'react';
import { Switch, Route } from 'react-router-dom';
import Home from 'pages/home';
import Settings from 'pages/settings';
import Display from 'pages/display';
import NotFound from 'pages/exception'
import styles from './App.less';
export default (props) => {
return (
<div className={ styles.app }>
<Switch>
<Route path='/settings' component={ Settings } />
<Route path='/display' component={ Display } />
<Route exact path='/' component={ Home } />
<Route component={ NotFound } />
</Switch>
</div>
)
}
Copy the code
Create an app.less file in the SRC directory and style your App components
App.less
.app {
padding: 60px;
}
Copy the code
Write Home, Settings, Display, NotFound components in the Pages directory
Home
Component is the root routing component used to jump toSetting
Interface andDisplay
interfaceSettings
Does the component demonstrate how to obtain and modify itmobx
The globalModel
Display
The component demonstrates how to use Mobx for synchronous and asynchronous data processingNotFound
Component is displayed when the correct route is not matched
I’m not going to post the code for Home, Settings, Display, it’s a long one, but if you need it, you can go to Github and take a look at it or download it. It’s convenient. Address: making
Modify the index.js file again
index.js
import React from 'react';
import ReactDom from 'react-dom';
import { Provider } from 'mobx-react'
import { LocaleProvider } from 'antd';
import { HashRouter } from 'react-router-dom';
import zh_CN from 'antd/lib/locale-provider/zh_CN';
import 'moment/locale/zh-cn';
import GlobalModel from './GlobalModel';
import App from './App';
const globalModel = new GlobalModel();
ReactDom.render(
<Provider globalModel={ globalModel} >
<LocaleProvider locale={zh_CN}>
<HashRouter>
<App />
</HashRouter>
</LocaleProvider>
</Provider>.document.querySelector('#root'));Copy the code
As you can see, there is a GlobalModel that holds the global universal data. The logic inside is relatively simple, so let’s take a look at it a little bit.
GlobalModel.js
import { observable, action } from 'mobx';
export default class GlobalModel {
@observable username = 'Ming';
@action
changeUserName = (name) = > {
this.username = name; }}Copy the code
Add the FETCH utility class for network requests
Since we need to carry out asynchronous operation of network request in Display component, fetch is introduced here for network request.
Install fetch related plug-ins:
npm install whatwg-fetch qs --save
Copy the code
Write the network request utility class
Create the request.js file in the utils directory.
utils/request.js
import 'whatwg-fetch';
import { stringify } from 'qs';
* @param {*} url * @param {*} data */
export const get = (url, data) = > {
const newUrl = url + '? ' + stringify(data) + (stringify(data) === ' ' ? ' ' : '&') +'_random=' + Date.now();
return fetch(newUrl, {
cache: 'no-cache'.headers: {
'Accept': 'application/json'.'Content-Type': 'application/json; charset=utf-8'
},
method: 'GET',
})
.then(response= > response.json());
}
* @param {*} url * @param {*} data */
export const post = (url, data) = > {
return fetch(url, {
body: JSON.stringify(data),
cache: 'no-cache'.headers: {
'Accept': 'application/json'.'Content-Type': 'application/json; charset=utf-8'
},
method: 'POST',
})
.then(response= > response.json()) // parses response to JSON
}
Copy the code
At this point, the simple React framework is complete
After executing NPM run start, you can see that the interface looks like this.
The Home interface:
Settings interface:
The Display interface:
NotFound interface:
5. Configure React project packaging
Json file to add an execution script:
{
...,
"scripts": {
"start": "webpack-dev-server --config webpack/webpack.config.dev.js",
"build": "webpack --config webpack/webpack.config.prod.js"
},
...
}
Copy the code
Configure the webpack.config.prod.js file
Most of these modules and Plugins and resolve are consistent with the development environment. So let’s start with the configuration in the webpack.config.dev.js file.
- Change the mode property value to: ‘production’
- Change the devTool property value to ‘hidden-source-map’
- Delete all configuration of the devServer property.
- Delete the use of thermal loading plug-ins: · webpack. HotModuleReplacementPlugin `,
Add the optimization attribute for code compression
Install related plug-ins:
npm install uglifyjs-webpack-plugin optimize-css-assets-webpack-plugin --save-dev
Copy the code
Add code compression configuration:
webpack.config.prod.js
. ;const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin"); . ;module.exports = {
mode: 'production'.devtool: 'hidden-source-map'.entry:... .output: {... },plugins: [...]. .module: {... },optimization: {
// Package compressed js/ CSS files
minimizer: [
new UglifyJsPlugin({
uglifyOptions: {
compress: {
// UglifyJs deletes unused code without warning
warnings: false.// Delete all 'console' statements, compatible with Internet Explorer
drop_console: true.// Inline variables that are defined but used only once
collapse_vars: true.// Extract static values that occur multiple times but are not defined as variables to reference
reduce_vars: true,},output: {
// Most compact output
beautify: false.// Delete all comments
comments: false,}}}),new OptimizeCSSAssetsPlugin({})
],
splitChunks: {
cacheGroups: {
styles: {
name: 'styles'.test: /\.(css|less)/.chunks: 'all'.enforce: true.reuseExistingChunk: true // Indicates whether to use the existing chunk. True indicates that if the chunk contains modules that have been extracted, no new chunk will be generated.
},
commons: {
name: 'commons'.chunks: 'initial'.minChunks: 2.reuseExistingChunk: true
},
vendors: {
name: 'vendors'.test: /[\\/]node_modules[\\/]/.priority: - 10.reuseExistingChunk: true}}},runtimeChunk: true
},
resolve: {...}
}
Copy the code
Extract CSS code using the mini-CSs-extract-plugin
Install related plug-ins:
npm install mini-css-extract-plugin --save-dev
Copy the code
Configure the mini-CSS-extract-plugin plugin:
- in
plugins
Property to introduce - will
module
的rules
Used in thestyle-loader
Replace withMiniCssExtractPlugin.loader
webpack.config.prod.js
. const MiniCssExtractPlugin =require('mini-css-extract-plugin');
module.exports = { ... .plugins: [...new MiniCssExtractPlugin({
filename: 'public/styles/[name].[contenthash:8].css'.chunkFilename: 'public/styles/[name].[contenthash:8].chunk.css'})].modules: {
rules: [..., {test: /\.(css|less)$/.exclude: /node_modules/.use: [
{
- loader: 'style-loader'
+ loader: MiniCssExtractPlugin.loader
},
...
]
},
{
test: /\.(css|less)$/.exclude: /node_modules/.use: [
{
- loader: 'style-loader'+ loader: MiniCssExtractPlugin.loader }, ... ] },... ] },... }Copy the code
Define the current production environment using the DefinePlugin plug-in
webpack.config.prod.js
. module.exports = { ... .plugins: [...new webpack.DefinePlugin({
// Define the NODE_ENV environment variable as production
'process.env': {
NODE_ENV: JSON.stringify('production'}})],... }Copy the code
Clean up the dist directory using the clean-webpack-plugin
In the process of packaging, some file names used hash values, resulting in different files each time, so some redundant files were generated in DIST. So we can clean up the dist directory before each packing.
Install plug-in:
npm install clean-webpack-plugin --save-dev
Copy the code
Using plug-ins:
webpack.config.prod.js
. .module.exports = { ... .plugins: [...new CleanWebpackPlugin()
],
...
}
Copy the code
Add other optimization configurations
- Add STATS to configure some statistics that appear when filtering packaging.
- Add the Performance configuration to turn off the performance prompt
webpack.config.prod.js
module.exports = { ... .stats: {
modules: false.children: false.chunks: false.chunkModules: false
},
performance: {
hints: false}}Copy the code
Package the project for release
Packaging project
Run the NPM run build command. After the console is packaged, the dist folder is added to the root directory.
Publish projects using Nginx
Here I am using Nginx as the server, published locally.
Nginx download: nginx.org/en/download… .
Once the download is complete, the decompression is complete. Open the Nginx directory, find a conf folder, find the nginx.conf file, modify the configuration in the Nginx:
Change the HTML labeled in the figure to DIST.
We can then safely place the generated dist folder directly into the Nginx installation directory. (The dist directory should be the same as the conf directory).
Start Nginx service:
start nginx
Copy the code
Open your browser and type http://127.0.0.1 or http://localhost to see that our project is running properly.
Nginx other commands:
# Stop Nginx service
nginx -s stop
Restart the Nginx service
nginx -s reload
# exit nginx
nginx -s quit
Copy the code
For more information about Ngnix, please refer to: Nginx official documentation
Note: Nginx commands need to be executed under Nginx installation!
Use webpack-merge to introduce webPack common configuration
If you look at the webpack.config.dev.js and webpack.config.prod.js files, you can see a lot of code and configuration duplication. So we can write a webpack.common.js file and put our common configuration into it, The webpack-merge plug-in is then imported into the webpack.config.dev.js and webpack.config.prod.js files, respectively.
Plug-in installation:
npm install webpack-merge --save-dev
Copy the code
Use:
+ const merge = require('webpack-merge');
+ const common = require('./webpack.common.js');
+ module.exports = merge(common, {
+ mode: 'production', +... +});Copy the code
Here is how to use webPack-merge. Due to the long space, I will not post the specific configuration code in the three files. You can check the configuration file after using Webpack-Merge on GitHub.
Seven, this article source address
react-mobx-starter
Welcome Star, thank you!
If there is any problem in the article and code, please correct it, thank you!
Viii. Reference documents
Webpack website
Build a Webpack environment configuration from scratch (with Demo)
Production environment configuration using Webpack (with Demo)