复制第6步package.json中的内容 使用npm/cnpm/yarn
demo码源
https://github.com/ITxiaochong/react-build
手动搭建react开发环境
配置参考 https://blog.csdn.net/weixin_34396103/article/details/91382217
1.创建项目
yarn init
2.安装webpack
yarn add --dev webpack@4.41.4 webpack-cli@3.3.10 webpack-dev-server@3.10.1
3.安装react react-dom
yarn add react react-dom
4.安装babel[4个]
yarn add --dev babel-core @babel/core babel-loader @babel/preset-react
5.在源码目录配置.babelrc
{
"presets": ["@babel/preset-react"]
}
6.package.json
{
"name": "react-build",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "webpack-dev-server --config config/webpack.dev.js",
"build": "webpack --config config/webpack.prod.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@babel/core": "^7.7.7",
"@babel/preset-react": "^7.7.4",
"babel-core": "^6.26.3",
"babel-loader": "^8.0.6",
"clean-webpack-plugin": "^3.0.0",
"css-loader": "^3.4.2",
"file-loader": "^6.0.0",
"html-webpack-plugin": "^3.2.0",
"mini-css-extract-plugin": "^0.9.0",
"node-sass": "^4.13.1",
"postcss-loader": "^3.0.0",
"postcss-preset-env": "^6.7.0",
"sass-loader": "^8.0.2",
"style-loader": "^1.1.3",
"url-loader": "^4.0.0",
"webpack": "^4.41.4",
"webpack-cli": "^3.3.10",
"webpack-dev-server": "^3.10.1",
"webpack-manifest-plugin": "^2.2.0"
},
"dependencies": {
"react": "^16.12.0",
"react-dom": "^16.12.0"
},
"browserslist": {
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
],
"production": [
">0.2%",
"not dead",
"not ie <= 11",
"not op_mini all"
]
}
}
7.在源码根目录配置webpack.dev.js和webpack.prod.js
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const ManifestPlugin = require("webpack-manifest-plugin");
//设置webpack环境
process.env.NODE_ENV = 'development';
module.exports = {
mode: 'development',
entry: './src/index.jsx', //必须使用‘./’开头不然识别不出来
output: {
path: path.resolve(__dirname, 'build'),
filename: 'static/js/bundle.js'
},
plugins: [new HtmlWebpackPlugin({
template: 'index.html',
filename: 'index.html',
favicon:'favicon.ico'
}),
new ManifestPlugin
],
module: {
rules: [{
test: /\.js|jsx$/,
use: 'babel-loader',
exclude: /node_modules/ //打包时不会被babel 做 es6 => es5
}, {
test: /favicon\.ico/,
use: {
loader: "file-loader",
options: {
name: "./favicon.ico"
}
}
}, {
test: /((?<!favicon)\.ico)|\.(png|jpe?g|gif)/,
use: {
loader: 'url-loader',
options: {
limit: 1024 * 8, //8kb以下的会被base64化
outputPath: 'static/images/',
name: '[hash:10].[ext]', //这里不是使用[name],为了避免重复图片
esModule: false //使用commonjs
}
}
}, {
test: /\.webp$/,
use: { loader: 'file-loader', options: { name: 'assets/webp/[name].[ext]' } }
}, {
test: /\.svg$/,
use: { loader: 'file-loader', options: { name: 'assets/svg/[name].[ext]' } }
}, {
test: /\.scss|sass$/,
use: [
"style-loader",
{ loader: "css-loader", options: { sourceMap: true } },
{
loader: "postcss-loader",
options: {
indent: "postcss",
plugins: () => [require("postcss-preset-env")()],
sourceMap: true
}
},
{ loader: "sass-loader", options: { sourceMap: true } }
]
}]
},
devServer: {
port: 3000, //监听端口
contentBase: './build', //基于目录
hot: true, //开启热更新
open: true //弹出浏览器
},
devtool: "cheap-module-eval-source-map",
// 引入资源省略后缀、资源别名配置
resolve: {
extensions: ['.js', '.jsx', '.json'],
alias: {
'@': path.join(__dirname, './src'),
'~': __dirname
}
}
};
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const ManifestPlugin = require("webpack-manifest-plugin");
//设置webpack环境
process.env.NODE_ENV = 'production';
//插件创建
const htmlPlugin = new HtmlWebpackPlugin({
template: 'index.html', //因为这里是相对于根目录
filename: 'index.html',
favicon:'favicon.ico',
minify: {
collapseWhitespace: true, //代码压缩
removeAttributeQuotes: true, //移除引号
removeComments: true, //移除注释
},
hash: true
});
const miniCssExtractPlugin = new MiniCssExtractPlugin({
filename: 'static/css/main.css',
chunkFilename: '[id].css',
hmr: process.env.NODE_ENV === 'development', //开发模式开启热加载 并且设置hot
reloadAll: true, // if hmr does not work, this is a forceful method.
});
module.exports = {
mode: 'production',
entry: './src/index.jsx', //必须使用‘./’开头不然识别不出来
output: {
path: path.resolve(__dirname, 'build'),
filename: 'static/js/bundle.js' //直接可以写js,这样js文件会被打包入build/js/build.js
},
plugins: [htmlPlugin, new CleanWebpackPlugin, miniCssExtractPlugin, new ManifestPlugin],
module: {
rules: [{
test: /\.js|jsx$/,
use: 'babel-loader',
exclude: /node_modules/ //打包时不会被babel 做 es6 => es5
}, {
test: /favicon\.ico/,
use: {
loader: "file-loader",
options: {
name: "./favicon.ico"
}
}
}, {
test: /((?<!favicon)\.ico)|\.(png|jpe?g|gif)/,
use: {
loader: 'url-loader',
options: {
limit: 1024 * 8, //8kb以下的会被base64化
outputPath: 'static/images/',
name: '[hash:10].[ext]', //这里不是使用[name],为了避免重复图片
esModule: false //使用commonjs
}
}
}, {
test: /\.webp$/,
use: { loader: 'file-loader', options: { name: 'assets/webp/[name].[ext]' } }
}, {
test: /\.svg$/,
use: { loader: 'file-loader', options: { name: 'assets/svg/[name].[ext]' } }
}, {
test: /\.scss|sass$/,
use: [
/* 3 js中的css抽成单独文件并且加入link */
MiniCssExtractPlugin.loader,
/* 2 css加载到js中 */
{ loader: "css-loader", options: { sourceMap: true } },
{
loader: "postcss-loader", //1-2 添加css前缀
options: {
indent: "postcss",
// package.json中的 browserslist区分开发和生成环境
plugins: () => [require("postcss-preset-env")()],
sourceMap: true
}
},
/* 1 将sass转换为css */
{ loader: "sass-loader", options: { sourceMap: true } }
]
}]
},
devtool: "source-map",
// 引入资源省略后缀、资源别名配置
resolve: {
extensions: ['.js', '.jsx', '.json'],
alias: {
'@': path.join(__dirname, './src'),
'~': __dirname
}
}
};