文件结构分析


env.js

// Load environment variables from .env* files. Suppress warnings using silent// if this file is missing. dotenv will never modify any environment variables// that have already been set.  Variable expansion is supported in .env files.// https://github.com/motdotla/dotenv// https://github.com/motdotla/dotenv-expand//注释其实写的很清楚,用dotenv和dotenv-expand工具读取所有.env*文件,获取变量dotenvFiles.forEach(dotenvFile => {  if (fs.existsSync(dotenvFile)) {    require('dotenv-expand')(      require('dotenv').config({        path: dotenvFile,      })    );  }});//最后赋值给process.env对象// Stringify all values so we can feed into Webpack DefinePlugin  const stringified = {    'process.env': Object.keys(raw).reduce((env, key) => {      env[key] = JSON.stringify(raw[key]);      return env;    }, {}),  };

modules.js
其实就两个函数,为了读取jsconfig.json或者tsconfig.json文件中的配置,两个文件不能同时存在.


paths.js文件前面说过了


pnpTs.js 这块确实不太清楚,不敢乱讲。看内容是关于typescript的,有ts-pnp插件配置,有大神帮忙解答下。


webpack.config.js
所有webpack基础配置(除了devServer)都在这里面了


暴露一个函数接口,参数就是环境变量

module.exports = function(webpackEnv) {  const isEnvDevelopment = webpackEnv === 'development';  const isEnvProduction = webpackEnv === 'production';  ...}

通过'development'或者'production'去加载不同的配置,

return {    mode: isEnvProduction ? 'production' : isEnvDevelopment && 'development',    bail: isEnvProduction,    devtool: isEnvProduction      ? shouldUseSourceMap        ? 'source-map'        : false      : isEnvDevelopment && 'cheap-module-source-map',    entry: [      isEnvDevelopment &&        require.resolve('react-dev-utils/webpackHotDevClient'),      paths.appIndexJs,    ].filter(Boolean),    output: {      path: isEnvProduction ? paths.appBuild : undefined,      pathinfo: isEnvDevelopment,      filename: isEnvProduction        ? 'static/js/[name].[contenthash:8].js'        : isEnvDevelopment && 'static/js/bundle.js',                  futureEmitAssets: true,           chunkFilename: isEnvProduction        ? 'static/js/[name].[contenthash:8].chunk.js'        : isEnvDevelopment && 'static/js/[name].chunk.js',           publicPath: publicPath,           devtoolModuleFilenameTemplate: isEnvProduction        ? info =>            path              .relative(paths.appSrc, info.absoluteResourcePath)              .replace(/\\/g, '/')        : isEnvDevelopment &&          (info => path.resolve(info.absoluteResourcePath).replace(/\\/g, '/')),    },    optimization: {      minimize: isEnvProduction,      minimizer: [              new TerserPlugin({          terserOptions: {            parse: {              ecma: 8,            },            compress: {              ecma: 5,              warnings: false,              inline: 2,            },            mangle: {              safari10: true,            },            output: {              ecma: 5,              comments: false,              ascii_only: true,            },          },          parallel: !isWsl,          cache: true,          sourceMap: shouldUseSourceMap,        }),        new OptimizeCSSAssetsPlugin({          cssProcessorOptions: {            parser: safePostCssParser,            map: shouldUseSourceMap              ? {                  inline: false,                  annotation: true,                }              : false,          },        }),      ],      splitChunks: {        chunks: 'all',        name: false,      },      runtimeChunk: true,    },    resolve: {      modules: ['node_modules', paths.appNodeModules].concat(        modules.additionalModulePaths || []      ),      extensions: paths.moduleFileExtensions        .map(ext => `.${ext}`)        .filter(ext => useTypeScript || !ext.includes('ts')),      alias: {        'react-native': 'react-native-web',      },      plugins: [        PnpWebpackPlugin,      ],    },    resolveLoader: {      plugins: [        PnpWebpackPlugin.moduleLoader(module),      ],    },    module: {      strictExportPresence: true,      rules: [        { parser: { requireEnsure: false } },        {          test: /\.(js|mjs|jsx|ts|tsx)$/,          enforce: 'pre',          use: [            {              options: {                formatter: require.resolve('react-dev-utils/eslintFormatter'),                eslintPath: require.resolve('eslint'),                              },              loader: require.resolve('eslint-loader'),            },          ],          include: paths.appSrc,        },        {                   oneOf: [            {              test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],              loader: require.resolve('url-loader'),              options: {                limit: 10000,                name: 'static/media/[name].[hash:8].[ext]',              },            },            {              test: /\.(js|mjs|jsx|ts|tsx)$/,              include: paths.appSrc,              loader: require.resolve('babel-loader'),              options: {                customize: require.resolve(                  'babel-preset-react-app/webpack-overrides'                ),                                plugins: [                  [                    require.resolve('babel-plugin-named-asset-import'),                    {                      loaderMap: {                        svg: {                          ReactComponent: '@svgr/webpack?-svgo,+ref![path]',                        },                      },                    },                  ],                ],                cacheDirectory: true,                cacheCompression: isEnvProduction,                compact: isEnvProduction,              },            },                       {              test: /\.(js|mjs)$/,              exclude: /@babel(?:\/|\\{1,2})runtime/,              loader: require.resolve('babel-loader'),              options: {                babelrc: false,                configFile: false,                compact: false,                presets: [                  [                    require.resolve('babel-preset-react-app/dependencies'),                    { helpers: true },                  ],                ],                cacheDirectory: true,                cacheCompression: isEnvProduction,                sourceMaps: false,              },            },            {              test: cssRegex,              exclude: cssModuleRegex,              use: getStyleLoaders({                importLoaders: 1,                sourceMap: isEnvProduction && shouldUseSourceMap,              }),              sideEffects: true,            },            {              test: cssModuleRegex,              use: getStyleLoaders({                importLoaders: 1,                sourceMap: isEnvProduction && shouldUseSourceMap,                modules: true,                getLocalIdent: getCSSModuleLocalIdent,              }),            },                        {              test: sassRegex,              exclude: sassModuleRegex,              use: getStyleLoaders(                {                  importLoaders: 2,                  sourceMap: isEnvProduction && shouldUseSourceMap,                },                'sass-loader'              ),                          sideEffects: true,            },                        {              test: sassModuleRegex,              use: getStyleLoaders(                {                  importLoaders: 2,                  sourceMap: isEnvProduction && shouldUseSourceMap,                  modules: true,                  getLocalIdent: getCSSModuleLocalIdent,                },                'sass-loader'              ),            },                        {              loader: require.resolve('file-loader'),                            exclude: [/\.(js|mjs|jsx|ts|tsx)$/, /\.html$/, /\.json$/],              options: {                name: 'static/media/[name].[hash:8].[ext]',              },            },          ],        },      ],    },    plugins: [     new HtmlWebpackPlugin(),        ...    ]}

webpackDevServer.config.js
devServer的配置文件,暴露一个函数

const protocol = process.env.HTTPS === 'true' ? 'https' : 'http';const host = process.env.HOST || '0.0.0.0';module.exports = function(proxy, allowedHost) {    //参数proxy代理配置和allowedHost     return {        ...        contentBase: paths.appPublic,//public文件夹路径        publicPath: '/',        hot: true,        https: protocol === 'https',        host,        public: allowedHost,        proxy,        before(app,server){            ...        }    }};