create-react-app项目配置全解析

目录
  • 引言
  • 准备工作
  • 启动命令
  • start.js
  • build.js
  • 目录结构
  • 配置解析
  • weback.config.js
  • 结语

引言

create-react-app(以下简称cra)作为react官方提供的脚手架工具,是目前生成react项目一个非常常用和主流的工具。很多企业级的应用搭建也是基于这个脚手架工具上二次开发。最近这段正好最近学习了webpack打包配置工程化的一些内容,索性就以cra的配置为例,对这段时间的学习做一个总结。

准备工作

首先,我们要用cra创建一个项目。这个没啥好说,有手就行。

create-react-app cra-config-project

这样初始化后创建出来项目的配置信息是隐藏在node_modules中的react-scripts中的。为了更直观的看到配置信息和修改,使用
eject命令将配置弹射出来。

yarn eject

完成后,我们项目配置的目录结构变成这样。

截屏2022-04-01 上午11.31.06.png

启动命令

打开package.json 文件,在scripts中看到以下三条命令

  "scripts": {
    "start": "node scripts/start.js",
    "build": "node scripts/build.js",
    "test": "node scripts/test.js"
  },

很明显,这分别是项目的启动开发环境,构建,测试的命令。我们重点看一下scripts中开发和构建的脚本。

start.js

在大概115行的位置,我们看到这样一段代码

    const devServer = new WebpackDevServer(serverConfig, compiler);
    // Launch WebpackDevServer.
    devServer.startCallback(() => {
    ...

很明显,这就是启动开发服务器的关键代码。在开发环境的时候,我们通过webpack-dev-server来启动一个本地的服务器,然后把随时构建出来的项目放在这个服务器下面运行。实例化这个devServer对象时候传的第一个参数是服务器的配置项,包括端口号,代理,静态资源目录等,具体见https://webpack.docschina.org/configuration/dev-server/;第二个参数是webpack的相关配置。如下所示:

  compiler = webpack(config);

build.js

构建脚本直接输出打包结果,自然不再需要启动本地服务。因此在获取了编译结果后,直接运行即可。因此在140行中

 compiler.run((err, stats) => {
   //...
 }

在代码中我们可以看到构建时,编译过程通过promise封装,对各种错误情况进行了处理。

目录结构

在看具体的配置之前,让我们回到这张图,看一下eject命令都弹射出了哪些配置放到了项目目录中来。

截屏2022-04-01 上午11.37.56.png

比起初使状态,现在的项目目录中除了装有启动脚本文件的目录scripts外,另外增加的就是config目录。打开config目录,webpack.config.js和webpackDevServer.config.js赫然在目,根据这个文件名我们可以很明显得知,这两个文件一个是webpack的配置,一个是开发服务器devServer 的配置。接下来,我们就可以从这两个文件按图索骥,学习cra的基本配置了。

配置解析

weback.config.js

在webpack.config.js中,默认导出了一个接受一个环境变量作为返回一个配置对象的方法。那传这个环境变量的目的不言而喻,一定有很多配置开发和生产环境是不同的。接下来重头戏来了,让我们来一条一条地学习下react官方对react开发环境是怎么配置的吧。

1.entry

 entry: paths.appIndexJs,

也就是 src目录下的index.js,因为cra构建的是单页应用,只有一个入口文件

  • output
 output: {
      path: paths.appBuild, // 打包后文件目录 在config目录中path.js中配置
      pathinfo: isEnvDevelopment, // webpack 在 bundle 中是否引入「所包含模块信息」的相关注释 开发环境打开 生产环境关闭
      filename: isEnvProduction
        ? 'static/js/[name].[contenthash:8].js'
        : isEnvDevelopment && 'static/js/bundle.js',//打包后文件名,生产环境根据name放在不同文件,开发环境放在一个bundle.js文件中
     chunkFilename: isEnvProduction
        ? 'static/js/[name].[contenthash:8].chunk.js'
        : isEnvDevelopment && 'static/js/[name].chunk.js',//chunk文件名称,生产环境和开发环境的区别是文件名中加上了hash
      assetModuleFilename: 'static/media/[name].[hash][ext]',//打包后的静态资源目录和文件名规则,如不指定直接放在打包后的根目录中
       publicPath: paths.publicUrlOrPath,//打包后的文件部署的url地址
       devtoolModuleFilenameTemplate: isEnvProduction
        ? info =>
            path
              .relative(paths.appSrc, info.absoluteResourcePath)
              .replace(/\\/g, '/')
        : isEnvDevelopment &&
          (info => path.resolve(info.absoluteResourcePath).replace(/\\/g, '/')),//自定义source-map文件数组使用名称
}
  • target
    target: ['browserslist'],

构建目标,从 browserslist-config 中推断出平台和 ES 特性 默认是browserslist 如果browserslist不存在,为web(cra项目中browserslist在package.json中)

  • bail
    bail: isEnvProduction,

错误出现时是否立即退出,生产环境下打开

  • devtool
devtool: isEnvProduction
      ? shouldUseSourceMap
        ? 'source-map'
        : false
      : isEnvDevelopment && 'cheap-module-source-map',

生成sourceMap方式,cra配置为生产环境source-map,开发环境为cheap-module-source-map。这两者的区别source-map调试时会显示列信息。devtool的配置有很多种,具体见https://webpack.docschina.org/configuration/devtool/#root

  • cache
    cache: {
      type: 'filesystem',//缓存生成的 webpack 模块和 chunk,来改善构建速度 开发环境下默认为type:'memory' 生产环境下关闭
      version: createEnvironmentHash(env.raw),
      cacheDirectory: paths.appWebpackCache,//缓存目录
      store: 'pack',
      buildDependencies: {
        defaultWebpack: ['webpack/lib/'],
        config: [__filename],
        tsconfig: [paths.appTsConfig, paths.appJsConfig].filter(f =>
          fs.existsSync(f)
        ),
      },
    },
  • optimization 优化项
 optimization: {
      minimize: isEnvProduction, //只在生产环境下开启
      minimizer: [
        //js TerserPlugin开启代码压缩
        new TerserPlugin({
          terserOptions: {
            parse: {
              ecma: 8,
            },
            compress: {
              ecma: 5,
              warnings: false,
              comparisons: false,
              inline: 2,
            },
            mangle: {
              safari10: true,
            },
            keep_classnames: isEnvProductionProfile,
            keep_fnames: isEnvProductionProfile,
            output: {
              ecma: 5,
              comments: false,
              ascii_only: true,
            },
          },
        }),
       //css 代码压缩
        new CssMinimizerPlugin(),
      ],
    },
  • resolve 解析
resolve: {
     modules: ['node_modules', paths.appNodeModules].concat(
       modules.additionalModulePaths || []
     ),//解析模块时应该搜索的目录
     extensions: paths.moduleFileExtensions
       .map(ext => `.${ext}`)
       .filter(ext => useTypeScript || !ext.includes('ts')),//如果有多个文件有相同的名字,但后缀名不同时webpack按顺序解析这些后缀名,使用户在引入模块时不带扩展名
     alias: {
       'react-native': 'react-native-web',
       ...(isEnvProductionProfile && {
         'react-dom$': 'react-dom/profiling',
         'scheduler/tracing': 'scheduler/tracing-profiling',
       }),
       ...(modules.webpackAliases || {}),
     },//创建 import 或 require 的别名,来确保模块引入变得更简单。可以给utils之类的文件色之后
     plugins: [
       new ModuleScopePlugin(paths.appSrc, [
         paths.appPackageJson,
         reactRefreshRuntimeEntry,
         reactRefreshWebpackPluginRuntimeEntry,
         babelRuntimeEntry,
         babelRuntimeEntryHelpers,
         babelRuntimeRegenerator,
       ]),
     ],
   },//应该使用的额外的解析插件列表
  • performance
performance: false,

关闭了webpack本身的性能提示,cra本身提供了FileSizeReporter来计算和报告文件大小

10. module终于进入到我们这个比较重要的module配置项,module配置决定了webpack如何解析非js的模块,项目中的各种静态资源,样式文件,乃至于ts tsx jsx等loader配置都是在这个模块中配置。

  • source-map loader
        shouldUseSourceMap && {
          enforce: 'pre',
          exclude: /@babel(?:\/|\\{1,2})runtime/,
          test: /\.(js|mjs|jsx|ts|tsx|css)$/,
          loader: require.resolve('source-map-loader'),
        },
  • 静态资源loader
            {
              test: [/\.avif$/],
              type: 'asset',
              mimetype: 'image/avif',
              parser: {
                dataUrlCondition: {
                  maxSize: imageInlineSizeLimit,
                },
              },
            },
            {
              test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
              type: 'asset',
              parser: {
                dataUrlCondition: {
                  maxSize: imageInlineSizeLimit,
                },
              },
            },
            {
              test: /\.svg$/,
              use: [
                {
                  loader: require.resolve('@svgr/webpack'),
                  options: {
                    prettier: false,
                    svgo: false,
                    svgoConfig: {
                      plugins: [{ removeViewBox: false }],
                    },
                    titleProp: true,
                    ref: true,
                  },
                },
                {
                  loader: require.resolve('file-loader'),
                  options: {
                    name: 'static/media/[name].[hash].[ext]',
                  },
                },
              ],
              issuer: {
                and: [/\.(ts|tsx|js|jsx|md|mdx)$/],
              },
            },

对各种格式的图片,svg文件的处理

  • 样式文件loader
            {
              test: cssRegex,
              exclude: cssModuleRegex,
              use: getStyleLoaders({
                importLoaders: 1,
                sourceMap: isEnvProduction
                  ? shouldUseSourceMap
                  : isEnvDevelopment,
                modules: {
                  mode: 'icss',
                },
              }),
              sideEffects: true,
            },
            {
              test: cssModuleRegex,
              use: getStyleLoaders({
                importLoaders: 1,
                sourceMap: isEnvProduction
                  ? shouldUseSourceMap
                  : isEnvDevelopment,
                modules: {
                  mode: 'local',
                  getLocalIdent: getCSSModuleLocalIdent,
                },
              }),
            },
            {
              test: sassRegex,
              exclude: sassModuleRegex,
              use: getStyleLoaders(
                {
                  importLoaders: 3,
                  sourceMap: isEnvProduction
                    ? shouldUseSourceMap
                    : isEnvDevelopment,
                  modules: {
                    mode: 'icss',
                  },
                },
                'sass-loader'
              ),
              sideEffects: true,
            },
            {
              test: sassModuleRegex,
              use: getStyleLoaders(
                {
                  importLoaders: 3,
                  sourceMap: isEnvProduction
                    ? shouldUseSourceMap
                    : isEnvDevelopment,
                  modules: {
                    mode: 'local',
                    getLocalIdent: getCSSModuleLocalIdent,
                  },
                },
                'sass-loader'
              ),
            },

对样式文件的处理, 主要是scss和css,cra 为什么没有配置less文件loader呢?开发环境下直接将所有样式注入head中style中,生产环境下结合下面要介绍的miniCssExtractPlugin插件抽出后放入不同css文件。另外,这里cra还对以.module.css 和 .module.sass后缀结尾的文件进行了css module处理,如果开发者需要对样式文件要用modules规则,可以将文件的后缀写成这两种。
11. 插件

  • htmlWebpackPlugin
      new HtmlWebpackPlugin(
        Object.assign(
          {},
          {
            inject: true,
            template: paths.appHtml,
          },
          isEnvProduction
            ? {
                minify: {
                  removeComments: true,
                  collapseWhitespace: true,
                  removeRedundantAttributes: true,
                  useShortDoctype: true,
                  removeEmptyAttributes: true,
                  removeStyleLinkTypeAttributes: true,
                  keepClosingSlash: true,
                  minifyJS: true,
                  minifyCSS: true,
                  minifyURLs: true,
                },
              }
            : undefined
        )
      ),

没啥好说的,地球人都知道的一个插件,把打包好的js文件注入到html中去,要注意的是在生产环境了开启了移除注释,合并空格一系列优化配置

  • InlineChunkHtmlPlugin
 isEnvProduction &&
        shouldInlineRuntimeChunk &&
        new InlineChunkHtmlPlugin(HtmlWebpackPlugin, [/runtime-.+[.]js/]),

这个插件辅助将一些chunk出来的模块内联到html中,比如runtime的代码,代码量不大。生产环境下开启

  • InterpolateHtmlPlugin
      new InterpolateHtmlPlugin(HtmlWebpackPlugin, env.raw),

HtmlWebpackPlugin的辅助插件,可以在html文件中加入变量

  • ModuleNotFoundPlugin
  • ReactRefreshWebpackPlugin
    isEnvDevelopment &&
        shouldUseReactRefresh &&
        new ReactRefreshWebpackPlugin({
          overlay: false,
        }),

热更新 react 组件,开发环境下开启

  • MiniCssExtractPlugin
 isEnvProduction &&
        new MiniCssExtractPlugin({
          filename: 'static/css/[name].[contenthash:8].css',
          chunkFilename: 'static/css/[name].[contenthash:8].chunk.css',
        }),

抽离css文件插件,生产环境下开启

  • WebpackManifestPlugin
  • ForkTsCheckerWebpackPlugin
      useTypeScript &&
        new ForkTsCheckerWebpackPlugin({
          async: isEnvDevelopment,
          typescript: {
            typescriptPath: resolve.sync('typescript', {
              basedir: paths.appNodeModules,
            }),
            configOverwrite: {
              compilerOptions: {
                sourceMap: isEnvProduction
                  ? shouldUseSourceMap
                  : isEnvDevelopment,
                skipLibCheck: true,
                inlineSourceMap: false,
                declarationMap: false,
                noEmit: true,
                incremental: true,
                tsBuildInfoFile: paths.appTsBuildInfoFile,
              },
            },
            context: paths.appPath,
            diagnosticOptions: {
              syntactic: true,
            },
            mode: 'write-references',
          },
          issue: {
            include: [
              { file: '../**/src/**/*.{ts,tsx}' },
              { file: '**/src/**/*.{ts,tsx}' },
            ],
            exclude: [
              { file: '**/src/**/__tests__/**' },
              { file: '**/src/**/?(*.){spec|test}.*' },
              { file: '**/src/setupProxy.*' },
              { file: '**/src/setupTests.*' },
            ],
          },
          logger: {
            infrastructure: 'silent',
          },
        }),

强制ts类型检查,如果项目使用了typescript编写的话使用

  • webpack.definePlugin
      new webpack.DefinePlugin(env.stringified),

wepack内置插件,在浏览器环境中定义环境变量

  • webpack.ignorePlugin
    new webpack.IgnorePlugin({
        resourceRegExp: /^\.\/locale$/,
        contextRegExp: /moment$/,
      }),

wepack内置插件,可以在打包时有选择的忽略一些内容,这里的配置是在打包moment的时候忽略moment的本地化内容

 isEnvDevelopment && new CaseSensitivePathsPlugin(),

解决为了解决mac系统中文件名大小写不敏感导致的打包不报错的问题,详见https://github.com/facebook/create-react-app/issues/240

结语

对于工程化经验特别少的开发者来说,webpack的配置浩如烟海,宛如一本百科全书让人望而兴叹。但是掌握webpack可以说是前端开发者进阶的必经之路。在学习的过程中,可以自己多搞一些demo,多去尝试和实践,就会渐渐的对它熟悉起来。之后,笔者计划对webpack打包的性能优化从配置项的各个维度做一个总结,请拭目以待。

以上就是create-react-app项目配置全解析的详细内容,更多关于create-react-app项目配置的资料请关注我们其它相关文章!

(0)

相关推荐

  • windows下create-react-app 升级至3.3.1版本踩坑记

    电脑原先使用npm install -g create-react-app命令全局安装过,根据文档先全局卸载npm uninstall -g create-react-app,然后采用npx create-react-app my-app创建项目.然而,项目创建完后,却只生成了node_modules,package.json,package_lock.json或yarn.lock这几个文件夹,同时报错: 解决 1.运行create-react-app -V查看版本号,发现还可以拿到版本号,说明

  • create-react-app使用antd按需加载的样式无效问题的解决

    官网给出的按需加载解决方案,先安装 babel-plugin-import 因为antd默认引入样式是less,所以需要手动配置为CSS,配置方法如下: 第一种方法:在package.json中配置,这种方法成功的前提是webpack里query下配置babelrc:true, 这样就会使用babelrc文件中的配置 "babel": { "presets": [ "react-app" ], "plugins": [ [ &

  • npx create-react-app xxx创建项目报错的解决办法

    手头有一台大学时代的Windows电脑,它此前没有装过create-react-app,只装了node环境.版本信息:node -> 10.16.3,npm -> 6.9.0.前几日闲的无事想给它装个React,结果失败了,报了错,所以有了下面这出. 安装过程 根据React官方文档(上图)可以发现,此时并不需要安装create-react-app工具,只要你的node >= 8.10 && npm >= 5.6,就可以直接使用npx create-react-ap

  • create-react-app安装出错问题解决方法

    create-react-app慢的解决方法 在操作官方实例Create React App时,需要执行指令: create-react-app my-app 来创建一个新的React应用.由于某原因,在拉取各种资源时,往往会巨慢,一直卡在 fetchMetadata: sill mapToRegistry uri http://registry.npmjs.org/whatwg-fetch 解决方案是换源,虽然平常使用cnpm来代替npm,但也只是使用新的指令而已,而在寻求create-rea

  • create-react-app常用自定义配置教程示例

    目录 引言 yarn安装依赖包报错 IE10下报错, Map 未定义 webpack添加 alias 解决跨域,反向代理配置 项目主要文件路径配置 关闭自动开启浏览器配置 修改 webpack output.publicPath 生产环境关闭 sourcemap eslint 配置 装饰器 Decorators 配置 区分环境 编译进度条配置 打包开启 gzip 压缩 生成 report.html 可视化打包分析 引入 antd 1.直接引入,样式直接用编译后的antd.css 2.引入 les

  • 详解create-react-app 2.0版本如何启用装饰器语法

    create-react-app(简称cra)已经更新之2.0.3版本, babel也更新至7.x版本, JavaScript装饰器语法虽然还不是标准, 但是借助于babel, 也能在项目里愉快的玩耍. cra2.0时代如何启用装饰器语法呢? 我们依旧采用的是react-app-rewired, 通过劫持webpack cofig对象, 达到修改的目的. yarn add react-app-rewired 修改package.json "scripts": { "start

  • create-react-app项目配置全解析

    目录 引言 准备工作 启动命令 start.js build.js 目录结构 配置解析 weback.config.js 结语 引言 create-react-app(以下简称cra)作为react官方提供的脚手架工具,是目前生成react项目一个非常常用和主流的工具.很多企业级的应用搭建也是基于这个脚手架工具上二次开发.最近这段正好最近学习了webpack打包配置工程化的一些内容,索性就以cra的配置为例,对这段时间的学习做一个总结. 准备工作 首先,我们要用cra创建一个项目.这个没啥好说,

  • 在Create React App中启用Sass和Less的方法示例

    关于创建 create-react-app 项目请查看:create-react-app 的安装与创建 . 关于在 less 和 sass 如何在 create-react-app 启用 CSS Modules,请查看我的上一篇文章: 在 Create React App 中使用 CSS Modules . 启用 Sass 语法编写 CSS create-react-app 脚手架中已经添加了 sass-loader 的支持,所以只需要安装 node-sass 插件即可 安装 node-sass

  • 在Create React App中使用CSS Modules的方法示例

    前提条件 请先进行全局安装 create-react-app 插件哈,安装命令:npm install create-react-app -g 先使用 create-react-app 命令下载一个脚手架工程,安装命令: # 使用 npx $ npx create-react-app my-app # 使用 npm $ npm init npx create-react-app my-app # 使用 yarn $ yarn create react-app my-app 运行项目 $ cd m

  • 在 React 项目中全量使用 Hooks的方法

    目录 前言 React Hooks useState useReducer 基础用法 进阶用法 useContext useEffect useLayoutEffect useRef useImperativeHandle useCallback useMemo React Redux Hooks useSelector useDispatch React Router Hooks useHistory useLocation useParams useRouteMatch 参考 结语 前言 此

  • Vue项目中配置pug解析支持

    Vue 的用法没有变化: <template lang="pug"> transition(name="sider") div.hello h3 {{msg}} p(:style="{color:'#000'}", :htmlData="msg") p label button(@click="clickMe") clickTest </template> 要注意的一点是: 标签后面

  • JavaWe商品项目保姆级解析IDEA版的图文教程(配置篇)

    首先这里我创建的工程是Maven工程(需要在磁盘中解压MAVEN,然后配置MAVEN的环境变量) 一. 先去maven 官网:http://maven.apache.org/download.cgi#下载压缩包,下拉页面可以看到好多版本,注意下载的版本版本后面是带.zip的:apache-maven-3.5.4-bin.zip,点击下载即可. 配置环境变量 一丶右键此电脑,点击属性 二丶选择高级系统设置 三丶点击环境变量 四丶添加一个新的系统变量MAVEN_HOME 变量值是你MAVEN解压的目

  • React项目配置prettier和eslint的方法

    目录 配置prettier和eslint 配置stylelint 保存自动修复 参考视频: https://www.bilibili.com/video/BV1rh411e7E5?vd_source=eee62ea3954ac01bff9e87e2a7b40084 prettier代码格式化 eslint js语法检查 stylellint css样式检查 配置prettier和eslint 1.初始化React项目 npx create-react-app study_react 2.安装vs

  • react创建项目启动报错的完美解决方法

    目录 一.预备知识: 二.创建项目步骤: 三.启动项目时可能出现的报错: 四.Todolist项目相关库: 五.GitHub搜索案例相关库: 六.尚硅谷路由案例相关库: 七.UI库案例相关库: 八.redux相关库: 一.预备知识: npm (也可以用yarn,本文以npm为例) npm介绍 全称为Node Package Manager,是随同NodeJS一起安装的包管理工具. 允许用户从NPM服务器下载别人编写的第三方包到本地使用. 允许用户从NPM服务器下载并安装别人编写的命令行程序到本地

  • django搭建项目配置环境和创建表过程详解

    1. 搭建项目配置环境和创建表 创建一个ttsx的项目 django-admin startproject ttsx 在ttsx下的__init__中导入mysql import pymysql pymysql.install_as_MySQLdb() 配置mysql 读写分离配置 # default:默认的配置的是主数据库 'default': { 'ENGINE': 'django.db.backends.mysql', 'HOST': 'localhost', 'PORT': 3306,

  • webpack5搭建一个简易的react脚手架项目实践

    目录 项目初始化 安装webpack 搭建脚手架目录结构 开启本地服务 配置css&sass 安装react的相关依赖 项目添加热更新 生产环境打包 总结 项目初始化 首先我们创建一个目录,初始化 npm,得到一个package.json文件. mkdir react-cli cd react-cli npm init -y 安装webpack 安装webpack和相关依赖.webpack-dev-server是开启开发环境的服务,webpack-merge是合并公共配置文件. npm inst

随机推荐