React-CRA 多页面配置(react-app-rewired)
更新时间:2019-01-11
版本信息:CRA v2.1.1 + Webpack v4.19.1 + react-app-rewired v1.6.2
一、前言
为什么要进行多页面配置
在使用 React 进行开发的过程中,我们通常会使用 create-react-app 脚手架命令来搭建项目,避免要自己配置 webpack,提高我们的开发效率。但是使用 create-react-app 搭建的项目是单页面应用,如果我们是做中后台管理页面或 SPA,这样是满足要求的,但如果项目有多入口的需求,就需要我们进行一些配置方面的修改。
一般现在有两种方式将脚手架搭建的项目修改为多入口编译:
- 执行
npm run eject
命令,弹出配置文件,进行自定义配置。请参见:React-CRA 多页面配置(npm run eject)。 - 使用 react-app-rewired 修改脚手架配置,在项目中安装 react-app-rewired 后,可以通过创建一个 config-overrides.js 文件来对 webpack 配置进行扩展。
本文对第 2 种方法给出具体配置方案,第 1 种方案详见:React-CRA 多页面配置(npm run eject)。在阅读本文之前,可以先了解一下第 1 种方案,有助于更好的理解本文内容。
webpack 基础
本文对 React 多页面应用配置的探讨是基于使用 create-react-app 脚手架命令构建的项目,并不是 webpack 多页面配置教程。但上述两种方案都应该具有一定的 webpack 的基础,实际上当你决定要改造或增强项目的构建打包配置的时候,你应该先对 webpack 进行一定的了解。
如果你之前使用 webpack v3.x 版本,这里附上 webpack v4.0.0 更新日志 以及 webpack4升级完全指南。
方案说明
通过使用 react-app-rewired 可以修改脚手架配置,从而实现扩展 webpack 配置,如增加对 less 文件的支持、增加 antd 组件的按需加载、处理 html 文档中的图片路径问题等,甚至可以将单页面入口编译修改为多页面入口编译的方式。
但是需要说明的是,我们可以通过 react-app-rewired 在不暴露配置文件的情况下达到扩展项目配置的目的,但并不建议使用这种方式进行多页面入口编译的配置,虽然本文主要就是介绍这种方案。本文的意义更多的是记录对这种方案的尝试,如果真的需要进行多页面配置,最好还是使用 npm run eject
暴露配置文件的方式。
主要原因是,通过 react-app-rewired 来实现多页面配置,是需要对脚手架原来的配置具有一定了解的,相较于 npm run eject
暴露配置文件的方式来说,这种方式是不太具有透明度的,后面维护的难度较大。本文方案完成的基础是,我之前已经通过 npm run eject
这种方式改造过一次多页面的配置,相当于说我已经拆过这个箱子了,我基本上了解了这个箱子里有什么,因此我在配置这个方案的过程中其实是对照着 npm run eject
这个方案中的配置文件来逐步进行的。
版本的变动
使用 CRA 脚手架命令生成的项目免去了我们自己配置 webpack 的麻烦,其内置的各种配置所需要的插件和依赖包的版本都是确定的,是经过了检验的成熟配置,不会因为其中某个依赖包版本的问题造成构建出错。但当我们决定要自己动手配置 webpack 的时候,就意味着我们要自己根据需要安装一些 plugin 或 npm 依赖包,而这些插件和依赖包的版本可能不适用于当前 CRA 的版本,从而造成构建过程中出现一些不可预期的错误。
因此,我们需要查看 CRA 脚手架项目的 package.json 文件,对于其中已经列出的 dependencies 依赖包,我们不应该改变这些依赖包的版本,而对于未列出的 npm 包,我们在使用的过程中需要逐个验证,不要一次性安装很多个 npm 包,否则执行构建命令的时候如果出错就会很难排查,最好是根据我们需要的功能逐个的安装相应的 npm 包,确定没有问题,再进行下一个功能的扩展。
正是由于版本的变动会对配置产生很大的影响,因此当我们确定了一个配置方案之后,不要再轻易去改动其中涉及到的 npm 包的版本,通过 package-lock.json 文件锁定版本,防止配置方案错乱。
另外,在本文编辑的时候,CRA 的最新版本为 v2.1.2,这个版本的 CRA 生成的项目,当前版本的 react-app-rewired v1.6.2 已经无法使用,具体信息可以参见 CRA >=2.1.2 breaking issue 2.1.2。至少在本文编辑的时候(2019.01.05),是无法适用于 CRA >=2.1.2 版本的,因此本文方案是基于最后一个可以适用的 CRA v2.1.1 版本来做的,package.json 文件中其他的 version 信息会附在方案后面。
2019-01-11 补充:上面提到的版本基本都是指 package.json 文件中列出的依赖包的版本,但是严格来讲还应包含一些构建配置中使用的 node.js 工具包,比如 globby、dir-glob等,这些工具包的版本更新也有可能会造成构建出错。这种情况的出现往往是无法预期的,它们造成的影响一般比较广泛,而不仅仅是出现在我们方案配置的过程中,这种错误基本上都会在 Github 上有相应的 issue 以及解决方法或修复措施,本文中也列出了遇到的一个这种类型的错误,详见 四、错误排查 章节中的 其他错误 一节。
二、准备工作
创建一个 CRA v2.1.1 项目
我们的配置方案是基于 CRA v2.1.1 脚手架项目进行改造的,因此首先我们要先创建一个 CRA 项目,详见官方文档:Create React App。
但是这样创建出来的项目默认是最新版本的 CRA 项目,我们在上文中已经说明,我们的配置方案是要求特定版本的 CRA 项目的,那么如何创建特定的 CRA v2.1.1 版本项目?
CRA 项目版本的核心其实就是 react-scripts 的版本,我们可以先创建一个最新版本的脚手架项目,然后更改为 v2.1.1 版本,具体如下:
- 创建一个最新版本的 CRA 项目,参见官方文档:Create React App;
- 删除 node_modules 文件夹,如果有 package-lock.json 文件或 yarn.lock 文件,也要一并删除,否则重新安装 node_modules 依赖包仍然会被锁定为原来的版本;
修改 package.json 文件,重新指定 react-scripts 的版本:
"dependencies": {- "react": "^16.7.0",+ "react": "^16.6.3",- "react-dom": "^16.7.0",+ "react-dom": "^16.6.3",- "react-scripts": "2.1.3"+ "react-scripts": "2.1.1" }
- 执行
yarn install
或npm install
重新安装项目依赖。
至此,我们已经创建了一个 CRA v2.1.1 项目,这将作为我们进行多页面入口编译改造的基础。
react-app-rewired 的用法
首先要学习 react-app-rewired 的用法,参照官方文档:How to rewire your create-react-app project。
主要是三点:
- 安装 react-app-rewired
- 创建一个 config-overrides.js 文件
- 修改 package.json 文件中的脚本命令
查看 CRA 项目原有的配置文件
上面我们提到在进行多页面配置之前,需要对脚手架原有的配置文件具有一定了解,那么如何查看原有的配置文件?
方法1:将使用 CRA 脚手架命令生成的项目拷贝一份,执行
npm run eject
暴露配置文件,eject 之后文件组织结构如下:my-app ├── config │ ├── jest │ ├── env.js │ ├── paths.js │ ├── webpack.config.dev.js │ ├── webpack.config.prod.js │ └── webpackDevServer.config.js ├── node_modules ├── public ├── scripts │ ├── build.js │ ├── start.js │ └── test.js ├── package.json ├── README.md └── src
其中 config 文件夹下就是脚手架原有的配置文件。
- 方法2:使用 CRA 脚手架命令生成项目,在 my-app/node_modules/react-scripts/config 路径下可以看到原有的配置文件
- 方法3:在 config-overrides.js 文件中将 webpack 配置对象输出在控制台,查看其结构
推荐使用第 1 种方式,便于我们在配置过程中查看和操作,第 3 种方式作为一种辅助手段,主要是用于改造过程中的调试和验证配置对象的改造结果的。
项目文件组织结构
在开始进行多入口配置之前,需要先明确项目的文件组织结构,这关系到我们如何准确获取所有的入口文件,这里不再详述,请参见React-CRA 多页面配置(npm run eject)中的项目文件组织结构一节。
三、具体方案
- 安装 react-app-rewired,创建 config-overrides.js 文件,修改 package.json 文件中的脚本命令。详见官方文档 How to rewire your create-react-app project。
执行
yarn start
命令,查看 http://localhost:3000,确保安装 react-app-rewired 操作没有问题。 修改文件组织结构。这里不再详述,参见上文 项目文件组织结构 一节。
CRA项目原文件组织结构为:my-app├── README.md├── node_modules├── package.json├── config-overrides.js // 安装 react-app-rewired 时创建的├── .gitignore├── public│ ├── favicon.ico│ ├── index.html│ └── manifest.json└── src├── App.css├── App.js├── App.test.js├── index.css├── index.js├── logo.svg└── serviceWorker.js
修改为多页面入口编译的文件组织结构:
// 本方案示例项目有两个页面 index.html & admin.html// 这里给出的文件组织结构是配置完成后的完整结构, 有些文件(如 src/setupProxy.js)的具体作用后面会给出说明my-app├── README.md├── node_modules├── package.json├── config-overrides.js // 安装 react-app-rewired 时创建的├── .gitignore├── public│ ├── favicon.ico│ ├── index.html // 作为所有页面的 html 模板文件│ └── manifest.json└── src├── index.js // 空白文件, 为了避免构建报错, 详见下文├── setupProxy.js // proxy 设置, 详见下文(在当前操作步骤中可以缺失)├── index // index.html 页面对应的文件夹│ ├── App.less│ ├── App.js│ ├── App.test.js│ ├── index.less // 使用 less 编写样式文件│ ├── index.js│ ├── logo.svg│ └── serviceWorker.js└── admin // admin.html 页面对应的文件夹├── App.less├── App.js├── App.test.js├── index.less // 使用 less 编写样式文件├── index.js├── logo.svg└── serviceWorker.js
执行
yarn start
命令,查看 http://localhost:3000/index.html 和 http://localhost:3000/admin.html,确保修改文件组织结构操作没有问题。这个示例项目是以 my-app/public/index.html 作为所有页面的 html 模板文件的,当然也可以分别指定不同的 html 模板文件,这是根据项目需要和项目文件组织结构决定的。在这个示例项目中,由于作为模板的 html 文件只需要有个根元素即可,因此将其作为所有入口的 html 模板文件。这样的话,每个页面的 <title></title> 就需要在各自页面中分别指定,一般可以在页面挂载之后进行操作,比如:
class App extends Component {componentDidMount() {document.title = 'xxx';}render() {return (...);}}
修改 config-overrides.js 文件,进行具体配置。实际上我们之后所有的操作都是在这个文件中进行的。
我们的测试方案是一个使用了 Ant Design、Redux、Less、Echarts 的多页面项目,需要达到以下要求:- 指定页面的多入口文件路径以及入口文件对应的 html 模板
- 实现 antd 组件的按需加载
- 增加对 less 文件的支持
- 更改输出的文件名
- 增加对 html 文档中图片路径的处理
- 更改代码拆分的配置
- 设置别名路径
上述每一个功能的实现,都需要执行 yarn start
或 yarn build
进行验证,确保操作成功后再进行下一项的配置。这里不再逐步说明配置的步骤,详见下面的代码及注释。
最终 config-overrides.js 文件内容如下:
/* config-overrides.js *//** @Author: mzhang.eric * @Last Modified time: 2019-01-10 18:37:17* @Description: 使用 react-app-rewired 扩展和改造 CRA v2.1.1 项目, 基于 webpack v4.19.1 + react-app-rewired v1.6.2 版本*/const rewireLess = require('react-app-rewire-less');const { injectBabelPlugin, paths } = require('react-app-rewired');const HtmlWebpackPlugin = require('html-webpack-plugin');const path = require('path');const fs = require('fs');const globby = require('globby');const appDirectory = fs.realpathSync(process.cwd());const resolveApp = relativePath => path.resolve(appDirectory, relativePath);// const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;module.exports = function override(config, env) {// 使用 babel-plugin-import 按需加载组件config = injectBabelPlugin(['import', { libraryName: 'antd', libraryDirectory: 'es', style: true }],config,);// 增加 less 支持config = rewireLess.withLoaderOptions({// 解决报错: Inline JavaScript is not enabled. Is it set in your options?javascriptEnabled: true,})(config, env);// 入口文件路径// const entriesPath = globby.sync([resolveApp('src') + '/*/index.js']);const entriesPath = globby.sync([resolveApp('src') + '/*/index.js'], {cwd: process.cwd()});paths.entriesPath = entriesPath;// 获取指定路径下的入口文件function getEntries(){const entries = {};const files = paths.entriesPath;files.forEach(filePath => {let tmp = filePath.split('/');let name = tmp[tmp.length - 2];if(env === 'production'){entries[name] = [require.resolve('./node_modules/react-scripts/config/polyfills.js'),filePath,];} else {entries[name] = [require.resolve('./node_modules/react-scripts/config/polyfills.js'),require.resolve('react-dev-utils/webpackHotDevClient'),filePath,];}});return entries;}// 入口文件对象const entries = getEntries();// 配置 HtmlWebpackPlugin 插件, 指定入口文件生成对应的 html 文件let htmlPlugin;if(env === 'production'){htmlPlugin = Object.keys(entries).map(item => {return new HtmlWebpackPlugin({inject: true,template: paths.appHtml,filename: item + '.html',chunks: [item],minify: {removeComments: true,collapseWhitespace: true,removeRedundantAttributes: true,useShortDoctype: true,removeEmptyAttributes: true,removeStyleLinkTypeAttributes: true,keepClosingSlash: true,minifyJS: true,minifyCSS: true,minifyURLs: true,},});});} else {htmlPlugin = Object.keys(entries).map(item => {return new HtmlWebpackPlugin({inject: true,template: paths.appHtml,filename: item + '.html',chunks: [item],});});}if (env === 'production') {for (let i = 0; i < config.plugins.length; i++) {let item = config.plugins[i];// 更改输出的样式文件名if (item.constructor.toString().indexOf('class MiniCssExtractPlugin') > -1) {item.options.filename = 'static/css/[name].css?_v=[contenthash:8]';item.options.chunkFilename = 'static/css/[name].chunk.css?_v=[contenthash:8]';}// SWPrecacheWebpackPlugin: 使用 service workers 缓存项目依赖if(item.constructor.toString().indexOf('function GenerateSW') > -1){// 更改输出的文件名item.config.precacheManifestFilename = 'precache-manifest.js?_v=[manifestHash]';}}// 更改生产模式输出的文件名config.output.filename = 'static/js/[name].js?_v=[chunkhash:8]';config.output.chunkFilename = 'static/js/[name].chunk.js?_v=[chunkhash:8]';} else {// 更改开发模式输出的文件名config.output.filename = 'static/js/[name].js';config.output.chunkFilename = 'static/js/[name].chunk.js';}// 修改入口config.entry = entries;// 修改 HtmlWebpackPlugin 插件for (let i = 0; i < config.plugins.length; i++) {let item = config.plugins[i];if (item.constructor.toString().indexOf('class HtmlWebpackPlugin') > -1) {config.plugins.splice(i, 1);}}config.plugins.push(...htmlPlugin);// 分析打包内容// config.plugins.push(new BundleAnalyzerPlugin());// 设置别名路径config.resolve.alias = {...config.resolve.alias,'@src': paths.appSrc, // 在使用中有些 Eslint 规则会报错, 禁用这部分代码的 Eslint 检测即可};// 处理 html 文档中图片路径问题config.module.rules[2].oneOf.push({test: /\.html$/,loader: 'html-withimg-loader'});// 修改 build/static/media/ 路径下的文件名for (let i = 0; i < config.module.rules[2].oneOf.length; i++) {const item = config.module.rules[2].oneOf[i];if(!item.options || !item.options.name){ continue;}let str = item.options.name.toString();if(str.indexOf('static/media/[name].[hash:8].[ext]') > -1){item.options.name = 'static/media/[name].[ext]?_v=[hash:8]';}}// 修改代码拆分规则,详见 webpack 文档:https://webpack.js.org/plugins/split-chunks-plugin/#optimization-splitchunksconfig.optimization = {splitChunks: {// 将所有入口点共同使用到的、次数超过 2 次的模块,创建为一个名为 commons 的代码块// 这种配置方式可能会增大初始的捆绑包,比如有些公共模块在首页其实并未用到,但也会打包进来,会降低首页的加载性能// 建议将非必需模块使用 import() 的方式动态加载,提升页面的加载速度// cacheGroups: {// commons: {// name: 'commons',// chunks: 'initial',// minChunks: 2// }// }// 将所有使用到的 node_modules 中的模块包打包为 vendors 代码块。(不推荐)// 这种方式可能会产生一个包含所有外部依赖包的较大代码块,建议只包含核心框架和工具函数代码,其他依赖项动态加载// cacheGroups: {// commons: {// test: /[\\/]node_modules[\\/]/,// name: 'vendors',// chunks: 'all'// }// }cacheGroups: {// 通过正则匹配,将 react react-dom echarts-for-react 等公共模块拆分为 vendor// 这里仅作为示例,具体需要拆分哪些模块需要根据项目需要进行配置// 可以通过 BundleAnalyzerPlugin 帮助确定拆分哪些模块包vendor: {test: /[\\/]node_modules[\\/](react|react-dom|echarts-for-react)[\\/]/,name: 'vendor',chunks: 'all', // all, async, and initial},// 将 css|less 文件合并成一个文件, mini-css-extract-plugin 的用法请参见文档:https://www.npmjs.com/package/mini-css-extract-plugin// MiniCssExtractPlugin 会将动态 import 引入的模块的样式文件也分离出去,将这些样式文件合并成一个文件可以提高渲染速度// 其实如果可以不使用 mini-css-extract-plugin 这个插件,即不分离样式文件,可能更适合本方案,但是我没有找到方法去除这个插件styles: { name: 'styles',test: /\.css|less$/,chunks: 'all', // merge all the css chunk to one fileenforce: true}},},};return config;};
四、错误排查
这里对方案形成过程中遇到的错误进行记录,这些错误有些是配置过程中必定会出现的,是需要我们进行改造的,也有些错误可能是操作不当主观造成的。
客观错误
这类错误是进行多页面入口编译改造过程中必定会遇到的,有些是由于项目文件组织结构的改变造成的,也有些是为了扩展项目配置而使用了源 CRA 脚手架项目未提供的 npm 包造成的,前者会出现哪些错误我们是可以明确知道的,后者相对来说是不确切的,但大多都是版本不适用造成的。
Could not find a required file.
Could not find a required file.
Name: index.js
Searched in: C:xxxxxxmy-appsrc错误描述:通过 create-react-app 脚手架搭建的项目以 my-app/src/index.js 作为应用入口,当执行构建脚本时如果检测到缺失了这个必要文件,node 进程会退出。但是在我们进行多页面入口改造的时候,src 直接路径下没有 index.js 文件,根据我们的文件组织结构,index.js 文件存在于每个独立页面的子文件夹下,如
my-app/src/index/index.js
my-app/src/admin/index.js
。
解决方法:在 src 直接路径下创建一个空的 index.js 文件。Inline JavaScript is not enabled. Is it set in your options?
// https://github.com/ant-design...
.bezierEasingMixin();^ Inline JavaScript is not enabled. Is it set in your options?
in C:xxxsrcmy-appnode_modulesantdesstylecolorbezierEasing.less (line 110, column 0)错误描述:less、less-loader 配置问题,提示需要允许行内 js 的执行,比如当我们在项目中使用 antd 组件时,如果引入的样式文件是 less 文件,构建时就会报上述错误。
解决方法:在 config-overrides.js 文件中增加 less 文件支持时,设置 javascriptEnabled 为 true。module.exports = function override(config, env) {...// 增加 less 支持config = rewireLess.withLoaderOptions({// 解决报错: Inline JavaScript is not enabled. Is it set in your options?javascriptEnabled: true,})(config, env);...return config;};
Failed to load resource: net::ERR_FILE_NOT_FOUND(build 版本)
错误描述:执行
yarn build
或npm run build
构建生产版本时,构建出的页面未能正确加载样式和脚本文件,chrome 检查工具报路径错误。
解决方法:修改 package.json 文件,指定 homepage 字段的值,本项目这里指定为相对路径。"homepage": "./",
When specified, "proxy" in package.json must be a string.
When specified, "proxy" in package.json must be a string.
Instead, the type of "proxy" was "object".
Either remove "proxy" from package.json, or make it a string.错误描述:我们在开发过程中一般会在 package.json 文件中配置 proxy 代理服务器,但是在 CRA 2.x 升级以后对 proxy 的设置做了修改,具体请参见官方升级文档:Move advanced proxy configuration to src/setupProxy.js
解决方法:移除 package.json 文件中有关 proxy 的设置,使用 http-proxy-middleware,在 src 目录下创建 setupProxy.js 文件。详细方法请参见上述文档。
主观错误
这类错误应该是可以避免的,但是在配置过程中可能会由于开发人员的不当操作造成出错,最主要的就是安装了错误版本的 plugin 或 npm 包,我们上面已经说过,对于项目原本的配置中在 package.json 文件中已经列出的 plugin 和 npm 包,不要再重复进行安装,否则可能重新安装的 plugin 或 npm 包版本是不适用的,从而造成出错。
例如,CRA v2.1.1 脚手架项目原有的 html-webpack-plugin 版本是 v4.0.0-alpha.2,是不需要再另外进行安装的。如果此时开发人员自己执行了 yarn add html-webpack-plugin
,从而将 html-webpack-plugin 的版本更换为了 v3.2.0,这就会造成构建报错:URIError: Failed to decode param '/%PUBLIC_URL%/favicon.ico'
URIError: Failed to decode param '/%PUBLIC_URL%/manifest.json'
,其他主观错误类似。
html-webpack-plugin 版本错误
URIError: Failed to decode param '/%PUBLIC_URL%/favicon.ico'
URIError: Failed to decode param '/%PUBLIC_URL%/manifest.json'错误描述:在执行
yarn start
构建命令时报错,页面空白。
解决方法:html-webpack-plugin 版本错误,在本文的配置方案中,应当使用"html-webpack-plugin": "4.0.0-alpha.2",
版本。- TypeError: Cannot read property 'state' of undefined(页面报错)
错误描述:编译构建过程没有报错,但页面报错:TypeError: Cannot read property 'state' of undefined。
解决方法:redux 版本错误,在本文的配置方案中,应当使用 redux <=3.7.2 版本。
其他错误
我们在上文 版本的变动 一节的补充中已经对此有所提及,这类错误主要是由 node.js 工具包版本的升级造成的,这些错误基本都是不可预期的,也无法在这里全部涵盖,只能就当前遇到的问题进行简要记录,可能随着时间的推移,还会出现其他的类似问题,也可能这些错误已经在后续的版本中被修复了,因此请勿纠结于这里记录的错误,如果遇到了这类错误,就查阅资料进行修正,如果没有遇到,则无须理会。
TypeError: Expected
cwd
to be of typestring
but received typeundefined
C:xxxmy-appnode_modulesdir-globindex.js:59
throw new TypeError(Expected \
cwd` to be of type `string` but received type `${typeof opts.cwd}``);
TypeError: Expectedcwd
to be of typestring
but received typeundefined
错误描述:本文的写作开始于 2019-01-05,在 2019-01-11 重新审核本文方案的时候,遇到了这个错误,主要是由于 dir-glob 版本的升级造成的,我们在配置脚本中使用了 globby 的 sync 方法,dir-glob 版本升级之后,这个方法的调用会使得 dir-glob 抛出上述错误。详细信息参见:Broken build do to major change from 2.0 to 2.2 以及 globby will pass opts.cwd = undefined to dir-glob, which leads to TypeError.
解决方法:这里给出的解决方法是限定于当前时间的,因为在本文编辑的时候(2019-01-11)这个 issue 还没有给出最终的解决方案,个人觉得可能会由 globby 进行修复。
/* config-overrides.js */ // 修改获取入口文件路径的代码 // const entriesPath = globby.sync([resolveApp('src') + '/*/index.js']); const entriesPath = globby.sync([resolveApp('src') + '/*/index.js'], {cwd: process.cwd()});
五、package.json 信息
本文的多页面配置方案是基于 CRA 脚手架项目的,项目的依赖包信息会包含在两个 package.json 文件中,其中脚手架自带的配置信息位于 my-app/node_modules/react-scripts/package.json
文件中,而我们根据项目需要自己增加的配置信息在 my-app/package.json
文件中,这里将本方案项目配置信息附录如下:
/* package.json */{"name": "my-app","version": "0.1.0","private": true,"dependencies": {"antd": "^3.12.1","babel-plugin-import": "^1.11.0","echarts": "^4.2.0-rc.2","echarts-for-react": "^2.0.15-beta.0","html-withimg-loader": "^0.1.16","http-proxy-middleware": "^0.19.1","react": "^16.6.3","react-app-rewire-less": "^2.1.3","react-app-rewired": "^1.6.2","react-dom": "^16.6.3","react-intl": "^2.7.2","react-lazyload": "^2.3.0","react-loadable": "^5.5.0","react-redux": "^6.0.0","react-scripts": "2.1.1","redux": "3.7.2","redux-promise-middleware": "^5.1.1","webpack-bundle-analyzer": "^3.0.3"},"scripts": {"start": "react-app-rewired start","build": "react-app-rewired build","test": "react-app-rewired test --env=jsdom","eject": "react-scripts eject"},"eslintConfig": {"extends": "react-app"},"browserslist": [">0.2%","not dead","not ie <= 11","not op_mini all"],"homepage": "./"}
React-CRA 多页面配置(react-app-rewired)相关推荐
- React路由404页面配置
path路径使用' * '号,表示匹配不到路径时使用该路径 代码示例: App.js import { BrowserRouter, Routes, Route, Link } from 'react ...
- 一个基于 React 开发的PC端音乐App
?一个基于 React 开发的PC端音乐App. 同时支持 Mac 与 Windows 系统.下载地址 项目使用 electron 作为外壳,webpack 作为打包工具,核心技术包括 React + ...
- 配置React的Babel 6和Webpack 2环境
Facebook的一帮子工程师在忙碌之余开发除了一套前段UI框架React.这个框架最大的有点就在于让UI的开发都基于组件,这样View都是根据props和state变化的. 项目地址:https:/ ...
- windows 下配置 react native 开发环境
windows 下配置 react native 开发环境 安装nvm 由于react native 需要使用 NodeJs 4.0以上版本,为了方便切换NodeJs,首先我们需要安装nvm. 你可以 ...
- 一个使用react native实现的短视频APP
黄豆仔短视频APP 一个使用react native实现的短视频APP.该项目是我没事搞着玩,用react native 写的.用了很多的库同时也修改了几个库: react-native-card-s ...
- 配置React项目的运行环境
两种配置react项目运行环境的方法 第一种方法,一步步配置项目的运行环境: 1)下载node,在官方网站可以下载,安装步骤不难,差不多一步步意 点next就行: 2)运行cmd 输入node -v ...
- 前端快闪三:多环境灵活配置react
大前端快闪:package.json文件知多少? 大前端快闪二:react开发模式 一键启动多个服务 你已经使用Create React App[1] 脚手架搭建了React应用,现在该部署了. 一般 ...
- 掘金后端 mysql优化_vue服务端渲染项目(ssr)仿掘金、后台页面是react spa、服务层nodejs、koa、mysql编写的一套多权限内容管理系统...
kite 后台演示网站账户:kitetest 密码:q123456 (资源有点大,可能要加载一段时间) 备注:因为项目是一直在写的,周期比较长,发出来的目的,就是希望大家多提建议,或者意见 然后我再来 ...
- react 返回一个页面_Fiber 内部: 深入理解 React 的新 reconciliation 算法
最近在看 React, 发现一篇深度好文, 忍不住就翻译了. React 是一个用于构建用户界面的库, 它的核心是跟踪组件状态变化并将它们更新到页面上. 在 React 中, 我们称这个过程为 rec ...
- react部署之页面空白
react部署之页面空白 问题:create-react-app build打包后,页面出现空白. 可能一: 控制台报错,js等文件找不到(404) 文件路径问题,只需修改package.json文件 ...
最新文章
- linux proc/xx/maps文件分析
- 模板类的全特化、偏特化
- 如何修改服务器mac地址,如何修改服务器mac地址
- Vmware怎样使用nat和桥接方式解决虚拟机联网问题
- 2021年的10种突破性技术
- n1服务器系统和小钢炮,教你N1小钢炮系统设置中其他一些应用和服务器的设置的相关方法教程...
- Linux Bridge的IP NAT细节探析-填补又一坑的过程
- 千元机PK苹果iphone
- SpringBoot导入导出你会用吗?(EasyPoi)
- 如何在eNSP将多台计算机ping通?
- Qt下的国际化方法—翻译文件(.ts .qm文件)的使用
- 图——有向图、无向图、有向网、无向网的邻接矩阵表示
- Apple Watch必备!KUNER充电表带登场
- 最新!互联网大厂各职级薪资对应关系图(2020年初)
- 1037 在霍格沃茨找零钱
- Chess Tournament (巧用思维)
- 为什么说python入门很简单,但是在你这很难?
- JavaScript——将json数组填充进excel表并下载保存
- 黄海导航软件测试,中国地质调查局工作标准DD2004—03地质调查GPS测量规程1范围.DOC...
- 基于webrtc的p2p H265播放器实现一