一个 WebPack5+Typescript5+React18的前端工程

最近在整理自己之前的一些demo,想整一个模板工程出来,方便随时使用。之前也有用一些快速创建的脚手架,但是发现要做一些特殊配置和修改总是很麻烦,所以就自己在试着搭了一个。地址

目录结构

md 复制代码
+--- README.md                 说明文档
\--- build                     webpack相关配置
    +--- webpack.prod.js       生产环境配置
    +--- webpack.dev.js        开发环境配置
    +--- webpack.dll.conf.js   dll生成配置,用于生成dll
    +--- webpack.base.js       基础配置  
+--- package.json            依赖说明文件
+--- public                  基础配置文件
+---build webpack相关配置
\---src 主要开发文件
    +---api                 axios 请求封装
    +---component           功能组件
    +---hooks               自定义钩子
    +---pages               页面组件
    +---router              路由配置,(新增页面,需要在这进行配置,
    +---utils               一些工具方法
+---.prettierrc             格式化配置
+---.eslintrc               代码检测配置
+---.gitignore              git忽略
+---tsconfig.json           ts配置
+---.env                    基础环境变量
+---dev.env                 开发环境变量
+---prod.env                生产环境变量

主要文件配置,及说明

webpack.base.js
  1. base中,读取并设置了写在.env里的全局变量
  2. 配置了地址别名src,因为使用的ts,所以在tsConfig.json中也要进行相应的配置
  3. 配置了常用的loader,ts-loader、babel-loader、sass-loader、css-loader
  4. 配置常用plugin,
javascript 复制代码
const path = require('path');// 路径
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');//  生成HTML文件
const MiniCssExtractPlugin = require('mini-css-extract-plugin');// css压缩
const { CleanWebpackPlugin } = require('clean-webpack-plugin');// 打包清理,删除dist目录
const dotenv = require('dotenv');
// 获取环境变量,projectRoot当前目录
const projectRoot = process.cwd();
const shared = {
    include: path.resolve(projectRoot, 'src'),
    exclude: /node_modules/,
};
// 解析env配置文件,设置环境变量
try {
    dotenv.config({ path: 'base.env' }); // 加载 .env 文件
    if (process.env.NODE_ENV === 'development') {
       dotenv.config({ path: 'dev.env' });
    } else {
       dotenv.config({ path: 'prod.env' });
    }
} catch (error) {
    throw new Error(`读取环境变量文件失败${error}`);
}
module.exports = {
    entry: `${projectRoot}/src/index.tsx`,
    cache: {
       type: 'filesystem',// 使用文件缓存
    },
    output: {
       filename: '[name].[chunkhash:8].js', // 打包后的文件名称
       path: path.resolve(projectRoot, './dist'), // 打包后的目录
       clean: true,
    },
    resolve: {
       extensions: ['.tsx', '.ts', '.js'],
       alias: {
          src: path.resolve(projectRoot, 'src'),//使用src作为地址别名
       },
    },
    module: {
       rules: [
          {
             test: /.tsx?$/,
             use: [
                {
                   loader: 'ts-loader',
                   options: {
                      transpileOnly: true,
                   },
                },
             ],
             ...shared,
          },
          {
             test: /.js$/,
             use: 'babel-loader',
             ...shared,
             issuer: /.[tj]sx?$/,
          },
          {
             test: /.s[ac]ss|css$/i,
             ...shared,
             use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader'],
             issuer: /.[tj]sx?$/,
          },
          {
             test: /.(png|svg|jpg|gif)$/,
             ...shared,
             type: 'asset/resource',
          },
          {
             test: /.(woff|woff2|eot|ttf|otf)$/,
             type: 'asset/resource',
             ...shared,
          },
       ],
    },
    plugins: [
       /* 根据模板生成HTML文件,模板可不传 */
       new HtmlWebpackPlugin({
          template: `${projectRoot}/public/index.html`,
       }),
       /* css 文件合并  */
       new MiniCssExtractPlugin({
          filename: '[name].[contenthash:8].css',
       }),
       // 定义环境变量,在项目文件中使用
       new webpack.DefinePlugin({
          'process.env.SERVER_URL': JSON.stringify(process.env.SERVER_URL),
          'process.env.MODE': JSON.stringify(process.env.MODE),
       }),
       new CleanWebpackPlugin(),
       function errorPlugin() {
          // 打包错误提示
          this.hooks.done.tap('done', stats => {
             if (
                stats.compilation.errors &&
                stats.compilation.errors.length &&
                process.argv.indexOf('--watch') === -1
             ) {
                console.error(stats.compilation.errors); //错误信息
                process.exit(2);
             }
          });
       },
    ],
    stats: 'errors-only',
};
webpack.dev.js
  1. 合并了上一步的基础配置,添加了开发代理,
  2. 后续有开发阶段的配置也可以加在这里
js 复制代码
const { merge } = require('webpack-merge');
const baseConfig = require('./webpack.base.js');
const defConfig = merge(baseConfig, {
    mode: 'development',
    devtool: 'source-map',//开启sourceMap,方便调试
    devServer: {
       proxy: [
          {
             context: ['/api', '/aa'],//代理
             target: process.env.TEST_SERVER_URL,//在dev.env中配置
             changeOrigin: true,
             pathRewrite: { '^/api': '/api' },//根据自己后台配置
          },
       ],
    },
});
module.exports = defConfig;
webpack.prod.js
  1. 添加一些打包优化方式,terser-webpack-plugin 提高打包速度
  2. webpack.DllReferencePlugin 缓存文件
js 复制代码
const { merge } = require('webpack-merge');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const webpack = require('webpack');
const baseConfig = require('./webpack.base.js');
const TerserPlugin = require('terser-webpack-plugin');
//使用dll,必须在打包前先生成manifest webpack --config .\build\webpack.dll.conf.js
const manifest = require('./dist/vendor.manifest.json');
const prodConfig = merge(baseConfig, {
    mode: 'production',
    optimization: {
       minimizer: [new TerserPlugin({//使用terser进行压缩
          minify: TerserPlugin.swcMinify,
          terserOptions: {},
       })],
       splitChunks: {
          minSize: 10, // 当文件大小小于该值时,不会生成单独的chunk文件
          cacheGroups: {
             commons: {
                // 对使用的公共文件进行抽离
                name: 'commons',
                chunks: 'all',
                minChunks: 2, // 最小公共次数
             },
          },
       },
    },
    plugins: [
       // 生成dll
       new webpack.DllReferencePlugin({
          context: __dirname,
          manifest,// manifest 就是之前打包出来的 json 文件
       }),
       /* css压缩 */
       new CssMinimizerPlugin({
          test: /.css$/,
       }),
    ],
})
module.exports = prodConfig;
webpack.dll.conf
  1. 使用DllPlugin 可以将特定的类库提前打包然后引入
js 复制代码
const path = require('path');
const webpack = require('webpack');
module.exports = {
    mode: 'production',
    entry: {
       vendor: ['react', 'react-dom'], // 将你想要打包的第三方库列在这里
    },
    output: {
       filename: '[name].dll.js',
       path: path.resolve(__dirname, 'dist'),
       library: '[name]_dll', // 将输出的 DLL 模块名设为全局变量
    },
    plugins: [
       new webpack.DllPlugin({
          name: '[name]_dll',
          path: path.resolve(__dirname, 'dist', '[name].manifest.json'),
       }),
    ],
};
首次 yarn build之前,需要 webpack --config webpack.dll.conf.js生成依赖文件
tsconfig.json
  • 配置地址别名必填项 baseUrlpaths(要和webpack.base.js里一一对应)
json 复制代码
{
    "exclude": [
       "node_modules",
       "dist"
    ],
    "include": [
       "src"
    ],
    "compilerOptions": {
       "outDir": "./dist/",
       "noImplicitAny": true,
       "target": "es5",
       "baseUrl": ".",
       "paths": {
          "src/*": [
             "src/*"
          ]
       },
       "lib": [
          "dom",
          "dom.iterable",
          "esnext"
       ],
       "allowJs": true,
       "skipLibCheck": true,
       "esModuleInterop": true,
       "allowSyntheticDefaultImports": true,
       "strict": true,
       "forceConsistentCasingInFileNames": true,
       "noFallthroughCasesInSwitch": true,
       "module": "esnext",
       "moduleResolution": "node",
       "resolveJsonModule": true,
       "isolatedModules": true,
       "noEmit": false,
       "jsx": "react-jsx"
    }
}
packge.json
  • 根据目录结构,配置好start、build
json 复制代码
"scripts": {
    "test": "echo "Error: no test specified" && exit 1",
    "start": "webpack-dev-server --config ./build/webpack.dev.js    --hot --open ",
    "build": "webpack --config ./build/webpack.prod.js",
    "dll": "webpack --config ./build/webpack.dll.conf.js",
    "lint": "eslint "src/**/*.{js,ts,tsx}" --fix"
},

快速开始

  • 克隆下来就可以直接使用
  • axios,和模板页面都是现成的
bash 复制代码
    git clone https://github.com/mobei12/React-ts-webpack.git

欢迎留言共同进步 🤝

相关推荐
sunny_12 小时前
⚡️ vite-plugin-oxc:从 Babel 到 Oxc,我为 Vite 写了一个高性能编译插件
前端·webpack·架构
jonjia16 小时前
模块、脚本与声明文件
typescript
jonjia16 小时前
配置 TypeScript
typescript
jonjia16 小时前
TypeScript 工具函数开发
typescript
jonjia16 小时前
注解与断言
typescript
jonjia16 小时前
IDE 超能力
typescript
jonjia16 小时前
对象类型
typescript
jonjia16 小时前
快速搭建 TypeScript 开发环境
typescript
jonjia16 小时前
TypeScript 的奇怪之处
typescript
jonjia17 小时前
类型派生
typescript