mkdir react_project
cd react_project
package.json 文件npm init
webpack 和 webpack-cli 作为 dev 依赖项npm i webpack@4 webpack-cli@3 -D
更新 package.json 文件
{
"name": "react_project",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "webpack --mode development",
"build": "webpack --mode production"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"webpack": "^4.17.1",
"webpack-cli": "^3.1.0"
}
}
react 和 react-dom 作为依赖npm i react@16 react-dom@16 -S
npm i babel-loader@8 @babel/core @babel/preset-env @babel/preset-react -D
** 注:babel 7 使用了 @babel 命名空间来区分官方包,因此以前的官方包 babel-xxx 改成了 @babel/xxx
webpack.config.js 和 .babelrc 文件,并配置 babel-loader 及 babel 选项module.exports = {
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader'
}
}
]
}
};
{
"presets": ["@babel/preset-env", "@babel/preset-react"]
}
index.js 文件渲染组件import React from 'react';
import ReactDOM from 'react-dom';
const Index = () => {
return <div>Hello React!</div>;
};
ReactDOM.render(<Index />, document.getElementById('index'));
index.html 文件<!DOCTYPE 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、Webpack4 and Babel 7</title>
</head>
<body>
<section id="index"></section>
</body>
</html>
html-webpack-plugin 作为 dev 依赖项,并配置 webpack.config.jsnpm i html-webpack-plugin -D
const HtmlWebPackPlugin = require('html-webpack-plugin');
module.exports = {
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader'
}
}
]
},
plugins: [
new HtmlWebPackPlugin({
template: './src/index.html',
filename: './index.html'
})
]
};
这个插件会将 js 代码通过 <script> 注入到 HTML 文件中
webpack-dev-server 作为 dev 依赖项npm i webpack-dev-server -D
package.json 的 start 脚本{
"name": "react_project",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "webpack-dev-server --mode development --open",
"build": "webpack --mode production"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"react": "^16.4.2",
"react-dom": "^16.4.2"
},
"devDependencies": {
"@babel/core": "^7.0.0",
"@babel/preset-env": "^7.0.0",
"@babel/preset-react": "^7.0.0",
"babel-loader": "^8.0.0",
"html-webpack-plugin": "^3.2.0",
"webpack": "^4.17.1",
"webpack-cli": "^3.1.0",
"webpack-dev-server": "^3.1.6"
}
}
const webpack = require('webpack');
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const apiMocker = require('webpack-api-mocker');
const appDir = path.resolve(__dirname);
module.exports = {
entry: {
bundle: path.resolve(appDir, 'index.js'),
},
output: {
filename: 'bundle.web.js',
path: path.resolve(appDir, 'dist'),
},
module: {
rules: [{
test: /\.(js|jsx)$/,
include: [
path.resolve(appDir, 'src'),
path.resolve(appDir, './web/react-native-web.js')
],
use: [{
loader: 'babel-loader',
}],
},
{
test: /\.css$/,
use: [
{loader:'style-loader'},
{loader:'css-loader'}
],
},
{
test: /\.less$/,
use: [
{loader:'style-loader'},
{loader:'css-loader'},
{loader:'less-loader'}
]
},
{
test: /\.scss$/,
use: [
{loader:'style-loader'},
{loader:'css-loader'},
{loader:'sass-loader'}
]
},
{
test: /\.(gif|jpe?g|png|svg)$/,
use: {
loader: 'url-loader',
options: {
name: '[name].[ext]'
}
}
},
{
test: /\.ttf$/,
use: [
{
loader: 'file-loader',
options: {
name: '[hash].[ext]'
},
},
]
}
],
},
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(appDir, 'index.html'),
}),
new BundleAnalyzerPlugin({
analyzerMode: 'static',
openAnalyzer: false,
}),
new webpack.NormalModuleReplacementPlugin(
/^react-native$/,
path.resolve(appDir, './web/react-native-web.js')
),
new CleanWebpackPlugin()
],
resolve: {
extensions: ['.js', '.json'],
alias: {
'react-native$': 'react-native-web'
},
modules: ['node_modules'],
},
devServer: {
contentBase: path.resolve(appDir, 'dist'),
compress: true,
port: 8080,
host:'0.0.0.0',
disableHostCheck:true,
historyApiFallback:true,
before(app) {
apiMocker(app, path.resolve('mock/api.js'))
}
}
};