create-react-app 多頁應用配置

摘要

本文主要講的是如何使用 react-app-rewired 擴展 create-react-app 配置支持多頁應用,包含開啓 PWA, 支持 ant-design 按需加載,兼容 IE11。javascript

效果預覽

  • 第一次訪問

  • 登陸頁

  • 登陸成功,再次進入

初始化

建立項目

使用 create-react-app 建立項目html

npx create-react-app .
複製代碼

create-react-app: facebook.github.io/create-reac…java

react-app-rewired 初始化

  • 安裝 react-app-rewiredcustomize-cra
yarn add react-app-rewired customize-cra --dev
複製代碼
  • 增長 config-overrides.js 文件
// config-overrides.js
module.exports = function override(config, env) {
  // do stuff with the webpack config...
  return config;
};
複製代碼
  • 修改 package.json scripts
/* package.json */
    "scripts": {
- "start": "react-scripts start",
+ "start": "react-app-rewired start",
- "build": "react-scripts build",
+ "build": "react-app-rewired build",
- "test": "react-scripts test",
+ "test": "react-app-rewired test",
      "eject": "react-scripts eject"
    },
複製代碼

react-app-rewired: github.com/timarney/re…react

ant-design 按需加載

根據 ant-design 文檔修改 config-overrides.jswebpack

/* config-overrides.js */
+ const { override, fixBabelImports, addLessLoader } = require('customize-cra');

- module.exports = function override(config, env) {
- // do stuff with the webpack config...
- return config;
- };
+ module.exports = {
+ webpack: override(
+ fixBabelImports('import', {
+ libraryName: 'antd',
+ libraryDirectory: 'es',
+ style: true,
+ }),
+ fixBabelImports('ant-design-pro', {
+ libraryName: 'ant-design-pro',
+ libraryDirectory: 'lib',
+ style: true,
+ camel2DashComponentName: false,
+ }),
+ addLessLoader({
+ javascriptEnabled: true,
+ localIdentName: '[local]--[hash:base64:5]',
+ // modifyVars: { '@primary-color': '#1DA57A' },
+ }),
+ ),
+ };
複製代碼

參考文檔: ant.design/docs/react/…git

支持多頁面

修改入口文件

  1. 刪除默認的 src/index.js 入口文件和相關依賴
  2. 建立 src/pages/ 目錄
  3. 建立 src/pages/index.jssrc/pages/login.js
  4. 參考 dva 快速開始指南編寫 src/pages/index.jssrc/pages/login.js 已經相關依賴的代碼
  5. 多頁應用應該使用 hashHistory,注意修改

自定義 create-react-app 配置

/* config-overrides.js */
+ const supportMultiPage = (config, env) => {
+ // do stuff with the webpack config...
+ return config;
+ };

  module.exports = {
    webpack: override(
+ supportMultiPage,
      fixBabelImports('import', {
        libraryName: 'antd',
        libraryDirectory: 'es',
        style: true,
      }),
      ...
    ),
  },
複製代碼

修改默認入口文件和根目錄

/* config-overrides.js */
  const {
    override,
    fixBabelImports,
    addLessLoader,
  } = require('customize-cra');
+ const paths = require('react-scripts/config/paths');

+ paths.appIndexJs = `${paths.appSrc}/pages/index.js`;
+ paths.servedPath = './';

...

複製代碼

修改 HtmlWebpackPlugin 配置

/* config-overrides.js */
...
+ const HtmlWebpackPlugin = require('html-webpack-plugin');

...

+ const getEntryConfig = env => {
+ const arr = 'development' === env ? [require.resolve('react-dev-utils/webpackHotDevClient')] : [];
+ return entry => {
+ return [...arr, `${paths.appSrc}/pages/${entry}.js`];
+ };
+ };
+
+ const removePlugin = (plugins, name) => {
+ const list = plugins.filter(it => !(it.constructor && it.constructor.name && name === it.constructor.name));
+ if (list.length === plugins.length) {
+ throw new Error(`Can not found plugin: ${name}.`);
+ }
+ return list;
+ };
+
+ const genHtmlWebpackPlugin = env => {
+ const minify = {
+ removeComments: true,
+ collapseWhitespace: true,
+ removeRedundantAttributes: true,
+ useShortDoctype: true,
+ removeEmptyAttributes: true,
+ removeStyleLinkTypeAttributes: true,
+ keepClosingSlash: true,
+ minifyJS: true,
+ minifyCSS: true,
+ minifyURLs: true,
+ };
+ const config = Object.assign(
+ {},
+ { inject: true, template: paths.appHtml },
+ 'development' !== env ? { minify } : undefined,
+ );
+ return entry => {
+ return new HtmlWebpackPlugin({
+ ...config,
+ chunks: ['vendors', `runtime~${entry}.html`, entry],
+ filename: `${entry}.html`,
+ });
+ };
+ };
+
+ const supportMultiPage = (config, env) => {
+ const list = ['index', 'login'];
+ config.entry = {};
+ config.plugins = removePlugin(config.plugins, 'HtmlWebpackPlugin');
+ const getEntry = getEntryConfig(env);
+ const getHtmlWebpackPlugin = genHtmlWebpackPlugin(env);
+ list.forEach(it => {
+ config.entry[it] = getEntry(it);
+ config.plugins.push(getHtmlWebpackPlugin(it));
+ });
+
+ if ('development' === env) {
+ config.output.filename = 'static/js/[name].bundle.js';
+ }
+ return config;
+ };
...
複製代碼

修改 devServer,開發環境支持多頁面

/* config-overrides.js */
  ...
  module.exports = {
    webpack: override(
      ...
    ),
+ devServer: configFunction => {
+ return (proxy, allowedHost) => {
+ const config = configFunction(proxy, allowedHost);
+ config.historyApiFallback.rewrites = [{ from: /^\/login\.html/, to: '/build/login.html' }];
+ return config;
+ };
+ },
  };
複製代碼

開啓 PWA

修改 create-react-app 默認 GenerateSW 配置

/* config-overrides.js */
  ...
+ const WorkboxWebpackPlugin = require('workbox-webpack-plugin');
  ...
  const supportMultiPage = (config, env) => {
    ...
    if ('development' === env) {
      config.output.filename = 'static/js/[name].bundle.js';
    } else {
+ config.plugins = removePlugin(config.plugins, 'GenerateSW');
+ const workboxWebpackPlugin = new WorkboxWebpackPlugin.GenerateSW({
+ clientsClaim: true,
+ exclude: [/\.map$/, /asset-manifest\.json$/, /\.html$/],
+ importWorkboxFrom: 'local',
+ // navigateFallback: paths.servedPath + '/index.html',
+ // navigateFallbackBlacklist: [
+ // // Exclude URLs starting with /_, as they're likely an API call
+ // new RegExp('^/_'),
+ // // Exclude URLs containing a dot, as they're likely a resource in
+ // // public/ and not a SPA route
+ // new RegExp('/[^/]+\\.[^/]+$'),
+ // ],
+ });
+ config.plugins.push(workboxWebpackPlugin);
+ }
    return config;
  };
...

複製代碼

頁面入口文件中註冊 serviceWorker

/* src/pages/index.js 和 src/pages/login.js 中同時修改 */
+ import * as serviceWorker from '../serviceWorker';
  ...
+ serviceWorker.register();
複製代碼

兼容 IE11

增長 react-app-polyfill 依賴

yarn add react-app-polyfill
複製代碼

頁面入口文件開始位置 import

/* src/pages/index.js 和 src/pages/login.js 中同時修改 */
+ import 'react-app-polyfill/ie11';
+ import 'react-app-polyfill/stable';
複製代碼

開發環境支持

/* package.json */
    "browserslist": {
      "production": [
        ">0.2%",
        "not dead",
        "not op_mini all"
      ],
      "development": [
        "last 1 chrome version",
        "last 1 firefox version",
- "last 1 safari version",
+ "last 1 safari version",
+ "last 1 ie version"
      ]
    },
複製代碼

低版本瀏覽器升級提醒

  1. 修改 index.html 文件
+ <script>/*@cc_on window.location.href="http://support.dmeng.net/upgrade-your-browser.html?referrer="+encodeURIComponent(window.location.href); @*/</script>
  <title>React App</title>
複製代碼
  1. 修改 minifyJS 參數
const genHtmlWebpackPlugin = env => {
    const minify = {
      removeComments: true,
      collapseWhitespace: true,
      removeRedundantAttributes: true,
      useShortDoctype: true,
      removeEmptyAttributes: true,
      removeStyleLinkTypeAttributes: true,
      keepClosingSlash: true,
- minifyJS: true,
+ minifyJS: {
+ comments: '@cc_on',
+ },
      minifyCSS: true,
      minifyURLs: true,
    };
    ...
  };
複製代碼
相關文章
相關標籤/搜索