引言
我们平常做项目时,经常使用create-react-app脚手架,它可以帮我们快速生成一个零配置的react项目,它的webpack配置文件是对外隐藏的,但是想要针对项目进行优化配置,就需要借助其他工具和插件,比如react-app-rewired,或者运行eject命令,将配置文件暴露出来进行修改。那么怎么不使用脚手架,从零配置一个react项目呢?本文将为你介绍。
1、新建空白目录,并初始化
yarn init -y
2、安装开发依赖
// 打包,本地运行工具
yarn add webpack webpack-cli webpack-dev-server -D
// 安装webpack插件
yarn add html-webpack-plugin clean-webpack-plugin -D
// babel
yarn add @babel/core babel-loader @babel/preset-env @babel/preset-react -D
// 由于js中的有些api,babel不能转换,所以要用babel-pollyfill,
// 但是pollyfill转换时会造成大量重复代码,所以有了 babel-runtime
// 按装各种loader
yarn add style-loader css-loader scss-loader postcss-loader -D
// 加载图片
file-loader 解决CSS等文件中的引入图片路径问题
url-loader 当图片小于limit的时候会把图片BASE64编码,大于limit参数的时候还是使用file-loader 进行拷贝
yarn add file-loader url-loader -D
// 分离 Css
yarn add mini-css-extract-plugin -D
// 压缩JS和CSS
yarn add terser-webpack-plugin optimize-css-assets-webpack-plugin -D
// 打包前清空build目录
yarn add clean-webpack-plugin -D
// 加css3前缀
yarn add postcss-loader autoprefixer -D
3、引入外部链接,不被webpack打包
// 在html中添加
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script>
// 在js中使用
const jQuery = require("jquery");
import jQuery from 'jquery';
// webpack中配置
externals: {
jquery: 'jQuery'//如果要在浏览器中运行,那么不用添加什么前缀,默认设置就是global
},
4、打包时在html中插入cdn链接,不被webpack打包
// 需要安装 html-webpack-externals-plugin插件
const htmlWebpackExternalsPlugin= require('html-webpack-externals-plugin');
new htmlWebpackExternalsPlugin({
externals:[
{
module:'react',
entry:'https://cdn.bootcss.com/react/15.6.1/react.js',
global:'React'
},
{
module:'react-dom',
entry:'https://cdn.bootcss.com/react/15.6.1/react-dom.js',
global:'ReactDOM'
}
]
})
5、最终的webpack配置文件
const path = require('path');
// 处理template 模板
const HtmlWebpackPlugin = require('html-webpack-plugin')
// 抽离css,放到单独文件内
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
// 压缩丑化js代码
const TerserPlugin = require('terser-webpack-plugin')
// 压缩css代码
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin')
// 清空build目录
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const HtmlWebpackExternalsPlugin= require('html-webpack-externals-plugin')
module.exports = {
mode: 'development',
entry: './src/index.jsx',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
publicPath: './'
},
devtool: 'source-map',
// 优化项
optimization: {
minimizer: [
new TerserPlugin({
parallel: true,
cache: true
}),
//压缩css资源的
new OptimizeCSSAssetsPlugin({
assetNameRegExp:/\.css$/g,
//cssnano是PostCSS的CSS优化和分解插件。cssnano采用格式很好的CSS,并通过许多优化,以确保最终的生产环境尽可能小。
cssProcessor: require('cssnano')
})
],
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
include: path.join(__dirname, 'src'),
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
"presets": ["@babel/preset-env", "@babel/preset-react"],
}
}
},
{
test: /\.css$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: '/' //
}
}, 'css-loader', 'postcss-loader'],
},
{
test: /\.less$/,
use: [{loader: MiniCssExtractPlugin.loader}, 'css-loader','postcss-loader', 'less-loader'],
},
{
test:/\.(jpg|png|bmp|gif|svg)/,
use:[
{
loader:'url-loader',
options:{
limit: 4096, // 小于4k的图片转成base64编码
outputPath: 'images',
publicPath: './images'
}
}
]
}
]
},
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
template: './src/index.html', // 源文件
filename: 'index.html', // 产出文件
hash: true, //避免缓存,在产出的资源后加hash
}),
// 将css抽离成单个文件
new MiniCssExtractPlugin({
filename: 'css/[name].css',
chunkFilename:'css/[id].css'
}),
new HtmlWebpackExternalsPlugin({
externals:[
{
module:'react',
entry:'https://cdn.bootcss.com/react/15.6.1/react.js',
global:'React'
},
{
module:'react-dom',
entry:'https://cdn.bootcss.com/react/15.6.1/react-dom.js',
global:'ReactDOM'
}
]
})
],
devServer: {
port: 3000,
// 设置跨域请求,代理
"/api": {
target: 'http://localhost:3000',
pathRewrite:{"^/api":""}
}
},
// 重要:
resolve: {
// 可以在require和 import的时候不用加后缀,会从前往后找
extensions: [".js",".jsx",".json",".css"]
},
};
6、最终package.json文件
{
"name": "custom",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"scripts": {
"start": "webpack-dev-server",
"build": "webpack"
},
"dependencies": {
"@babel/core": "^7.8.6",
"@babel/preset-env": "^7.8.6",
"babel-loader": "^8.0.6",
"react": "^16.13.0",
"react-dom": "^16.13.0",
"react-router": "^5.1.2"
},
"devDependencies": {
"@babel/preset-react": "^7.8.3",
"autoprefixer": "^9.7.4",
"clean-webpack-plugin": "^3.0.0",
"css-loader": "^3.4.2",
"file-loader": "^5.1.0",
"html-webpack-externals-plugin": "^3.8.0",
"html-webpack-plugin": "^3.2.0",
"less": "^3.11.1",
"less-loader": "^5.0.0",
"mini-css-extract-plugin": "^0.9.0",
"optimize-css-assets-webpack-plugin": "^5.0.3",
"postcss-loader": "^3.0.0",
"sass-loader": "^8.0.2",
"scss-loader": "^0.0.1",
"style-loader": "^1.1.3",
"terser-webpack-plugin": "^2.3.5",
"url-loader": "^3.0.0",
"webpack": "^4.41.6",
"webpack-cli": "^3.3.11",
"webpack-dev-server": "^3.10.3"
}
}