react+typeScript环境配置

353 阅读2分钟

项目初始化

npm init

react配置

npm i react react-dom
npm i @types/react @types/react-dom -D
npm i -D babel-loader @babel/core @babel/preset-env @babel/preset-react @babel/polyfill
npm i core-js@2 # babel的按需引入依赖
npm i -D @babel/plugin-proposal-class-properties # 能够在class中自动绑定this的指向
npm i -D typescript awesome-typescript-loader # 处理ts,主要就靠它
npm i -D html-loader html-webpack-plugin # 顺便把html的支持做好

Webpack配置

npm i -D webpack webpack-cli webpack-dev-server webpack-merge

具体配置

const path = require('path');
const webpack = require('webpack');
const config = require('./config');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const argv = require('yargs').argv;
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer')
  .BundleAnalyzerPlugin;
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const merge = require('webpack-merge');

const bundleAnalyzerReport = argv.report; // 根据命令参数是否含有 'report' 来决定是否生成报告

const APP_PATH = path.resolve(__dirname, '../src');

const webpackConfig = {
  entry: {
    app: './src/index.tsx',
    vendor: ['react', 'react-dom'], // 不变的代码分包
  },
  output: {
    filename: 'js/[name].bundle.js',
    path: config.assetsRoot,
    publicPath: config.publicPath,
  },
  module: {
    rules: [
      {
        enforce: 'pre',
        test: /\.tsx?$/,
        exclude: /node_modules/,
        include: [APP_PATH],
        loader: 'eslint-loader',
        options: {
          emitWarning: true,
          emitError: true,
          fix: true, // 是否自动修复
        },
      },
      {
        oneOf: [
          {
            test: /\.(html)$/,
            loader: 'html-loader',
          },
          {
            test: /\.(j|t)sx?$/,
            include: APP_PATH,
            use: [
              {
                loader: 'babel-loader',
                options: {
                  presets: [
                    '@babel/preset-react', // jsx支持
                    ['@babel/preset-env', { useBuiltIns: 'usage', corejs: 2 }], // 按需使用polyfill
                  ],
                  plugins: [
                    [
                      '@babel/plugin-proposal-class-properties',
                      { loose: true },
                    ], // class中的箭头函数中的this指向组件
                  ],
                  cacheDirectory: true, // 加快编译速度
                },
              },
              {
                loader: 'awesome-typescript-loader',
              },
            ],
          },
          {
            test: /\.(less|css)$/,
            use: [
              { loader: 'style-loader' },
              {
                loader: 'css-loader',
                options: {
                  modules: false, // 如果要启用css modules,改为true即可
                },
              },
              {
                loader: 'less-loader',
                options: { javascriptEnabled: true },
              },
            ],
          },
          {
            test: /\.svg$/,
            use: ['@svgr/webpack'],
          },
          {
            test: /\.(jpg|jpeg|bmp|png|webp|gif)$/,
            loader: 'url-loader',
            options: {
              limit: 8 * 1024, // 小于这个大小的图片,会自动base64编码后插入到代码中
              name: 'img/[name].[hash:8].[ext]',
              outputPath: config.assetsDirectory,
              publicPath: config.assetsRoot,
            },
          },
          // 下面这个配置必须放在最后
          {
            exclude: [/\.(js|mjs|ts|tsx|less|css|jsx)$/, /\.html$/, /\.json$/],
            loader: 'file-loader',
            options: {
              name: 'media/[path][name].[hash:8].[ext]',
              outputPath: config.assetsDirectory,
              publicPath: config.assetsRoot,
            },
          },
        ],
      },
    ],
  },
  resolve: {
    extensions: ['.js', '.json', '.jsx', '.ts', '.tsx'], // 自动判断后缀名,引入时可以不带后缀
    alias: {
      '@': path.resolve(__dirname, '../src/'), // 以 @ 表示src目录
    },
  },

  plugins: [
    new HtmlWebpackPlugin({
      inject: true,
      template: config.indexPath,
      showErrors: true,
    }),
  ],
  optimization: {
    minimizer: [
      new OptimizeCSSAssetsPlugin({
        cssProcessorOptions: {
          safe: true,
          discardComments: { removeAll: true },
        },
      }),
    ],
    splitChunks: {
      chunks: 'all',
      minChunks: 2,
      maxInitialRequests: 5,
      cacheGroups: {
        // 提取公共模块
        commons: {
          chunks: 'all',
          test: /[\\/]node_modules[\\/]/,
          minChunks: 2,
          maxInitialRequests: 5,
          minSize: 0,
          name: 'common',
        },
      },
    },
  },
};

if (bundleAnalyzerReport) {
  webpackConfig.plugins.push(
    new BundleAnalyzerPlugin({
      analyzerMode: 'static',
      openAnalyzer: false,
      reportFilename: path.join(config.assetsRoot, './report.html'),
    })
  );
}

module.exports = webpackConfig;

需要安装对应的loader和plugin

TypeScript 配置

新建tsconfig.js

{
    "compilerOptions": {
        "target": "es5",
        "lib": ["dom", "dom.iterable", "esnext"],
        "typeRoots": [
            "src/types" // 指定 d.ts 文件的位置,根据具体情况修改
        ],
        "allowJs": true,
        "skipLibCheck": true,
        "esModuleInterop": true,
        "experimentalDecorators": true,
        "allowSyntheticDefaultImports": true,
        "strict": true,
        "forceConsistentCasingInFileNames": true,
        "module": "esnext",
        "moduleResolution": "node",
        "resolveJsonModule": true,
        "isolatedModules": true,
        "noEmit": true,
        "jsx": "react",
        "baseUrl": "."
    },
    "include": ["src"],
    "exclude": ["./node_modules"]
}

eslint + prettier

npm i -D eslint babel-eslint eslint-loader eslint-plugin-jsx-control-statements
npm i -D eslint-plugin-react @typescript-eslint/parser @typescript-eslint/eslint-plugin