现在react开发,公司用的要么是create-react-app这个脚手架,要么是umi,这些脚手架也是基于webpack的,只是添加了一些实践中比较好用功能进去,最近就想研究一下怎么通过webpack从0到1搭建一套适合自己的React开发环境。
这次探索使用的主要软件及版本如下:
Node: v14
Webpack: v5.72.0
React: v18
Babel: v7
typescript:v4.6.3
Babel 7 配置
这是想重点说一下Babel 7的配置,这个还是有点让人疑惑的,先看结论
广大前端工程人员babel终极配置:
"presets": [['@babel/preset-env', {targets: "ie 11","useBuiltIns": "usage", "corejs": "3.6" }]]
需要安装的包有
@babel/runtime 引入helpers函数 必须
npm install --save core-js@3 配置中指定的corejs版本
@babel/preset-env 预设
@babel/core 核心
babel-loader webpack处理core-js的loader
广大js库开发者终极配置:
presets: ['@babel/preset-env'],
"plugins": [
[
"@babel/plugin-transform-runtime",
{
"helpers": true,
"corejs": 3,
"regenerator": true,
"useESModules": false,
"absoluteRuntime": false,
"version": "^7.17.9"
}
]
]
Babel7的配置感觉babel的官网说的并不是太清楚,对于没有babel配置经验的人来说,很难分清楚各种配置项的含义,好在babel7已经大大的简化了相关polyfill的引入,我是通过这篇文章才算理解了babel的正确配置,见链接 babel教程
webpack.common.config.js
下边直接贴出webpack.common.config.js的配置,webpack区分dev环境和prod环境,webpack.common.config.js是公共配置
这里主要配置了项目入口 ,项目打包配置,ts的支持(babel-loader和ts-loader),图片,字体等静态资源等配置
const path = require("path");
const webpack = require("webpack");
const chalk = require("chalk");
const HtmlWebpackPlugin = require("html-webpack-plugin");
//这个要node12以上了
//const EslintWebpackPlugin = require('eslint-webpack-plugin');
const ProgressBarPlugin = require("progress-bar-webpack-plugin");
/** @type {(import('webpack').Configuration} */
const config = {
entry: path.resolve(__dirname, "../src/index.tsx"), // 默认入口,如果一样可以不设置
output: {
// 出口
path: path.resolve(__dirname, "../dist"), // 默认打包文件夹,如果一样可以不设置
//filename: 'main.js' // 默认打包目录文件名,如果一样可以不设置
filename: "js/[name].bundle.js",
assetModuleFilename: "images/[name].[ext][query]",
publicPath: "/",
clean: true,
},
resolve: {
alias: {
"@": path.resolve(__dirname, "../src"), // 同时配置 '@' 符号作为 src 的绝对路径别名方便后续开发
},
extensions: [".ts", ".tsx", ".js", ".json"],
},
module: {
rules: [
{
test: /\.tsx?$/, //
exclude: /node_modules/, // 排除 node_modules 目录
use: [
{
loader: "babel-loader",
},
//这里使用ts-loader,内部还是调用tsc进行编译,还可选用 @babel/preset-typescript ,这用就不用安装typescript了
// https://blog.logrocket.com/babel-vs-typescript/
{
loader: "ts-loader",
},
],
},
{
test: /\.(png|jpe?g|gif)$/,
type: "asset/resource",
},
{
test: /\.(woff(2)?|eot|ttf|otf|svg|)$/,
type: "asset/inline",
},
],
},
plugins: [
//会在dist生成一个一样的index.html
new HtmlWebpackPlugin({
//template: "./public/index.html"
template: path.resolve(__dirname, "../public/index.html"),
}),
// new EslintWebpackPlugin({
// fix: true, // fix 参数能够自动修复部分错误
// extensions: ['js', 'ts', 'tsx'], // 需要检测的文件类型
// // 更多参数可以去查看 https://webpack.docschina.org/plugins/eslint-webpack-plugin/#root
// }),
new ProgressBarPlugin({
format: ` build [:bar] ${chalk.green.bold(
":percent"
)} (:elapsed seconds)`,
}),
],
stats: "minimal",
};
module.exports = config;
webpack.dev.config.js
这里主要是开发环境的相关配置,如热启动,路由模式,代理,css预处理(sass/less/postcss/autoprefixer)等。
const { merge } = require("webpack-merge");
const common = require("./webpack.common.config");
// const path = require("path");
module.exports = merge(common, {
mode: "development",
devtool: "source-map",
devServer: {
port: 9900, // 指定端口
open: false, // 自启浏览器
hot: true, // 局部热更新
compress: false,
historyApiFallback: true, // 支持 history 模式路由
// client: {
// logging: 'none'
// }
proxy: {
// 代理跨域 如果需要的话
"/insight": {
// target: "https://zen.kyligence.io/", // 目标代理接口地址
target: "https://api.zongliwei.com/api/v2/", // 目标代理接口地址
changeOrigin: true, // 是否跨域
pathRewrite: {
// "^/api": "/",
},
},
},
},
module: {
rules: [
// {
// //test: /\.(css|sass|scss)$/,
// test: /\.(sa|sc|c)ss$/,
// use: [
// "style-loader", // 把css内嵌到html的style标签中
// // 普通的css 会应用css-loader import 'a.css' img:url() 这种
// //css有不少高级用法,例如生成hash的类名 https://www.npmjs.com/package/css-loader
// {
// loader: "css-loader",
// options: {
// sourceMap: true, // 启用 css sourceMap
// },
// },
// {
// loader: "postcss-loader",
// options: {
// postcssOptions: {
// plugins: [
// [
// "autoprefixer",
// {
// overrideBrowserslist: ["last 4 version"],
// },
// ],
// ],
// },
// },
// },
// "sass-loader",
// ],
// exclude: /node_modules/,
// },
{
test: /\.(css|less)$/,
use: [
"style-loader", // 把css内嵌到html的style标签中
// 普通的css 会应用css-loader import 'a.css' img:url() 这种
{
loader: "css-loader",
options: {
// sourceMap: true, // 启用 css sourceMap
modules: {
auto: true,
localIdentName: "[local]__[hash:base64:6]",
},
},
},
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [
[
"autoprefixer",
{
overrideBrowserslist: ["last 4 version"],
},
],
],
},
},
},
{
loader: "less-loader",
options: {
// webpackImporter: true,
lessOptions: {
javascriptEnabled: true,
},
},
},
],
// include: [path.resolve(__dirname, "src", "less")],
// exclude: /node_modules/,
},
],
},
});
webpack.prod.config.js
这里主要配置了生产环境的相关优化,比如禁用source-map,js/css 压缩,定义打包文件名(hash) 等
const { merge } = require("webpack-merge");
//const path = require("path");
const common = require("./webpack.common.config");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = merge(common, {
mode: "production",
devtool: false, // 生产环境不需要 source-map
//js 代码压缩要用到 terser-webpack-plugin,但 webpack 5 内置了这个插件可一键开启
optimization: {
//生产环境开启terser-webpack-plugin
minimize: true,
},
output: {
filename: "js/app.js",
//filename: path.resolve(__dirname, "js/app.js"),
assetModuleFilename: "images/[name].[ext][query]",
//filename: 'js/[name].[contenthash].bundle.js', // 文件名哈希
//assetModuleFilename: 'images/[name].[contenthash][ext][query]', // 图片文件需要存放的位置,如果不设置会全部打包进根目录下
//publicPath: '/app/'
},
module: {
rules: [
{
//test: /\.(css|sass|scss)$/,
test: /\.(sa|sc|c)ss$/,
use: [
"style-loader", // 把css内嵌到html的style标签中
// 普通的css 会应用css-loader import 'a.css' img:url() 这种
//css有不少高级用法,例如生成hash的类名 https://www.npmjs.com/package/css-loader
{
loader: "css-loader",
options: {
sourceMap: true, // 启用 css sourceMap
},
},
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [
[
"autoprefixer",
{
overrideBrowserslist: ["last 4 version"],
},
],
],
},
},
},
"sass-loader",
],
exclude: /node_modules/,
},
{
//test: /\.(css|sass|scss)$/,
test: /\.less$/,
use: [
"style-loader", // 把css内嵌到html的style标签中
// 普通的css 会应用css-loader import 'a.css' img:url() 这种
{
loader: "css-loader",
options: {
sourceMap: true, // 启用 css sourceMap
},
},
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [
[
"autoprefixer",
{
overrideBrowserslist: ["last 4 version"],
},
],
],
},
},
},
{
loader: "less-loader",
options: {
lessOptions: {
javascriptEnabled: true,
},
},
},
],
exclude: /node_modules/,
},
],
},
plugins: [
// 启用 css 压缩插件
new MiniCssExtractPlugin({
filename: "css/[name].[contenthash].css",
//filename: './app.css'
}),
],
});
如何使用css modules (可配置css类名hash)
- 在global.t.ds中定义 "*.module.less"
- 把less文件名改为 xx.module.less
- 在文件中引入的时候用 import classes from 'xx.module.less'
- tsx中引入的时候用 classes['cls-name']
- webpack.dev.config.js中配置如下
options: {
// sourceMap: true, // 启用 css sourceMap
modules: {
auto: true,
localIdentName: "[local]__[hash:base64:6]",
},
},
如果不想用css modules,则把文件名改为 xx.less ,其它恢复成原样即可
脚手架地址: webpack-react-scaffolding
本文由 dealdot <dealdot#163.com> 创作, Full Stack Developer @ DeepBlue
本文最后编辑时间为: Dec 2, 2022 at 15:31 pm
转载请注明来源