This is an automated email from the ASF dual-hosted git repository. shuai pushed a commit to branch feat/1.3.0/ui in repository https://gitbox.apache.org/repos/asf/incubator-answer.git
commit 652f5de7c7c9b17a4dd04f5eed6d0412b68d5d17 Author: shuai <[email protected]> AuthorDate: Tue Mar 5 16:03:31 2024 +0800 fix: split main.js #809 #784 --- ui/config-overrides.js | 86 ++++++++++++++++++ ui/package.json | 2 + ui/pnpm-lock.yaml | 100 ++++++++++++++------- ui/src/components/Comment/index.tsx | 2 +- ui/src/components/SchemaForm/index.tsx | 2 +- ui/src/hooks/usePageUsers/index.tsx | 2 +- ui/src/i18n/init.ts | 8 +- ui/src/pages/Admin/index.tsx | 2 +- ui/src/pages/Questions/Ask/index.tsx | 3 +- .../components/Achievements/index.tsx | 2 +- .../Users/Notifications/components/Inbox/index.tsx | 2 +- ui/src/utils/common.ts | 43 ++++----- ui/src/utils/saveDraft.ts | 2 +- 13 files changed, 190 insertions(+), 66 deletions(-) diff --git a/ui/config-overrides.js b/ui/config-overrides.js index 293d6bc1..19698173 100644 --- a/ui/config-overrides.js +++ b/ui/config-overrides.js @@ -20,6 +20,7 @@ const { addWebpackModuleRule, addWebpackAlias, + setWebpackOptimizationSplitChunks, } = require("customize-cra"); const path = require("path"); @@ -37,6 +38,91 @@ module.exports = { use: "yaml-loader" })(config); + setWebpackOptimizationSplitChunks({ + maxInitialRequests: 20, + minSize: 20 * 1024, + minChunks: 2, + cacheGroups: { + automaticNamePrefix: 'chunk', + components: { + test: /[\\/]components[\\/]/, + name: 'components', + priority: 13, + minChunks: 2, + reuseExistingChunk: true, + enforce: true, + }, + commons: { + test: /[\\/]common[\\/]/, + name: 'common', + priority: 12, + minChunks: 2, + reuseExistingChunk: true, + enforce: true, + }, + i18next: { + name: 'i18next', + test: /[\/]node_modules[\/](i18next)[\/]/, + filename: 'static/js/[name].[contenthash:8].chunk.js', + priority: 11, + reuseExistingChunk: true, + minChunks: 1, + chunks: 'initial', + }, + reactBootstrap: { + name: 'react-bootstrap', + test: /[\/]node_modules[\/](react-bootstrap)[\/]/, + filename: 'static/js/[name].[contenthash:8].chunk.js', + priority: 10, + minChunks: 1, + chunks: 'initial', + reuseExistingChunk: true, + }, + codemirror: { + name: 'codemirror', + test: /[\/]node_modules[\/](codemirror)[\/]/, + priority: 9, + reuseExistingChunk: true, + enforce: true, + }, + nextShare: { + name: 'next-share', + test: /[\/]node_modules[\/](next-share)[\/]/, + filename: 'static/js/[name].[contenthash:8].chunk.js', + priority: 8, + reuseExistingChunk: true, + minChunks: 1, + chunks: 'initial', + }, + marked: { + name: 'marked', + test: /[\/]node_modules[\/](marked)[\/]/, + filename: 'static/js/[name].[contenthash:8].chunk.js', + priority: 7, + reuseExistingChunk: true, + minChunks: 1, + chunks: 'initial', + }, + nodesAsync: { + name: 'chunk-nodesAsync', + test: /[\/]node_modules[\/]/, + priority: 2, + minChunks: 2, + chunks: 'async', // 仅打包异步引用的依赖 + reuseExistingChunk: true, // 重复使用已经存在的块 + }, + nodesInitial: { + name: 'chunk-nodesInitial', + filename: 'static/js/[name].[contenthash:8].chunk.js', + test: /[\/]node_modules[\/]/, + priority: 1, + minChunks: 1, + chunks: 'initial', + reuseExistingChunk: true, + }, + }, + })(config); + // add i18n dir to ModuleScopePlugin allowedPaths const moduleScopePlugin = config.resolve.plugins.find(_ => _.constructor.name === "ModuleScopePlugin"); if (moduleScopePlugin) { diff --git a/ui/package.json b/ui/package.json index ac7e4411..99543e12 100644 --- a/ui/package.json +++ b/ui/package.json @@ -4,6 +4,7 @@ "private": true, "homepage": "/", "scripts": { + "analyze": "source-map-explorer 'build/static/js/*.js'", "start": "react-app-rewired start", "build": "react-app-rewired build", "lint": "eslint . --cache --fix --ext .ts,.tsx", @@ -38,6 +39,7 @@ "react-i18next": "^11.18.3", "react-router-dom": "^6.8.1", "semver": "^7.3.8", + "source-map-explorer": "^2.5.3", "swr": "^1.3.0", "zustand": "^4.1.1" }, diff --git a/ui/pnpm-lock.yaml b/ui/pnpm-lock.yaml index 77f3c9b1..a46f8f75 100644 --- a/ui/pnpm-lock.yaml +++ b/ui/pnpm-lock.yaml @@ -1,20 +1,3 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - lockfileVersion: '6.0' settings: @@ -94,6 +77,9 @@ importers: semver: specifier: ^7.3.8 version: 7.3.8 + source-map-explorer: + specifier: ^2.5.3 + version: 2.5.3 swr: specifier: ^1.3.0 version: 1.3.0([email protected]) @@ -2223,7 +2209,7 @@ packages: chalk: 4.1.2 emittery: 0.8.1 exit: 0.1.2 - graceful-fs: 4.2.10 + graceful-fs: 4.2.11 jest-changed-files: 27.5.1 jest-config: 27.5.1([email protected]) jest-haste-map: 27.5.1 @@ -2295,7 +2281,7 @@ packages: collect-v8-coverage: 1.0.1 exit: 0.1.2 glob: 7.2.3 - graceful-fs: 4.2.10 + graceful-fs: 4.2.11 istanbul-lib-coverage: 3.2.0 istanbul-lib-instrument: 5.2.0 istanbul-lib-report: 3.0.0 @@ -2324,7 +2310,7 @@ packages: engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} dependencies: callsites: 3.1.0 - graceful-fs: 4.2.10 + graceful-fs: 4.2.11 source-map: 0.6.1 /@jest/[email protected]: @@ -2350,7 +2336,7 @@ packages: engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} dependencies: '@jest/test-result': 27.5.1 - graceful-fs: 4.2.10 + graceful-fs: 4.2.11 jest-haste-map: 27.5.1 jest-runtime: 27.5.1 transitivePeerDependencies: @@ -4550,6 +4536,12 @@ packages: dependencies: node-int64: 0.4.0 + /[email protected]: + resolution: {integrity: sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g==} + engines: {node: '>= 0.4.0'} + hasBin: true + dev: false + /[email protected]: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} @@ -5914,7 +5906,7 @@ packages: resolution: {integrity: sha512-T0yTFjdpldGY8PmuXXR0PyQ1ufZpEGiHVrp7zHKB7jdR4qlmZHhONVM5AQOAWXuF/w3dnHbEQVrNptJgt7F+cQ==} engines: {node: '>=10.13.0'} dependencies: - graceful-fs: 4.2.10 + graceful-fs: 4.2.11 tapable: 2.2.1 /[email protected]: @@ -7899,7 +7891,7 @@ packages: '@jest/types': 27.5.1 chalk: 4.1.2 exit: 0.1.2 - graceful-fs: 4.2.10 + graceful-fs: 4.2.11 import-local: 3.1.0 jest-config: 27.5.1([email protected]) jest-util: 27.5.1 @@ -7930,7 +7922,7 @@ packages: ci-info: 3.4.0 deepmerge: 4.2.2 glob: 7.2.3 - graceful-fs: 4.2.10 + graceful-fs: 4.2.11 jest-circus: 27.5.1 jest-environment-jsdom: 27.5.1 jest-environment-node: 27.5.1 @@ -8034,7 +8026,7 @@ packages: '@types/node': 16.11.59 anymatch: 3.1.2 fb-watchman: 2.0.1 - graceful-fs: 4.2.10 + graceful-fs: 4.2.11 jest-regex-util: 27.5.1 jest-serializer: 27.5.1 jest-util: 27.5.1 @@ -8102,7 +8094,7 @@ packages: '@jest/types': 27.5.1 '@types/stack-utils': 2.0.1 chalk: 4.1.2 - graceful-fs: 4.2.10 + graceful-fs: 4.2.11 micromatch: 4.0.5 pretty-format: 27.5.1 slash: 3.0.0 @@ -8185,7 +8177,7 @@ packages: '@types/node': 16.11.59 chalk: 4.1.2 emittery: 0.8.1 - graceful-fs: 4.2.10 + graceful-fs: 4.2.11 jest-docblock: 27.5.1 jest-environment-jsdom: 27.5.1 jest-environment-node: 27.5.1 @@ -8220,7 +8212,7 @@ packages: collect-v8-coverage: 1.0.1 execa: 5.1.1 glob: 7.2.3 - graceful-fs: 4.2.10 + graceful-fs: 4.2.11 jest-haste-map: 27.5.1 jest-message-util: 27.5.1 jest-mock: 27.5.1 @@ -8238,7 +8230,7 @@ packages: engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} dependencies: '@types/node': 16.11.59 - graceful-fs: 4.2.10 + graceful-fs: 4.2.11 /[email protected]: resolution: {integrity: sha512-yYykXI5a0I31xX67mgeLw1DZ0bJB+gpq5IpSuCAoyDi0+BhgU/RIrL+RTzDmkNTchvDFWKP8lp+w/42Z3us5sA==} @@ -8256,7 +8248,7 @@ packages: babel-preset-current-node-syntax: 1.0.1(@babel/[email protected]) chalk: 4.1.2 expect: 27.5.1 - graceful-fs: 4.2.10 + graceful-fs: 4.2.11 jest-diff: 27.5.1 jest-get-type: 27.5.1 jest-haste-map: 27.5.1 @@ -8277,7 +8269,7 @@ packages: '@types/node': 16.11.59 chalk: 4.1.2 ci-info: 3.4.0 - graceful-fs: 4.2.10 + graceful-fs: 4.2.11 picomatch: 2.3.1 /[email protected]: @@ -8483,7 +8475,7 @@ packages: dependencies: universalify: 2.0.0 optionalDependencies: - graceful-fs: 4.2.10 + graceful-fs: 4.2.11 /[email protected]: resolution: {integrity: sha512-pfog5gdDxPdV4eP7Kg87M8/bHgshlZ5pybl+yKxAnCZ5O7lCIn7Ixydj03wOlnDQesky2BPyA91SQ+5Y/mNwzw==} @@ -9153,6 +9145,14 @@ packages: mimic-fn: 4.0.0 dev: true + /[email protected]: + resolution: {integrity: sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==} + engines: {node: '>=8'} + dependencies: + is-docker: 2.2.1 + is-wsl: 2.2.0 + dev: false + /[email protected]: resolution: {integrity: sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==} engines: {node: '>=12'} @@ -10792,6 +10792,13 @@ packages: resolution: {integrity: sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==} dev: true + /[email protected]: + resolution: {integrity: sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==} + hasBin: true + dependencies: + glob: 7.2.3 + dev: false + /[email protected]: resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} hasBin: true @@ -11151,6 +11158,25 @@ packages: /[email protected]: resolution: {integrity: sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==} + /[email protected]: + resolution: {integrity: sha512-qfUGs7UHsOBE5p/lGfQdaAj/5U/GWYBw2imEpD6UQNkqElYonkow8t+HBL1qqIl3CuGZx7n8/CQo4x1HwSHhsg==} + engines: {node: '>=12'} + hasBin: true + dependencies: + btoa: 1.2.1 + chalk: 4.1.2 + convert-source-map: 1.8.0 + ejs: 3.1.8 + escape-html: 1.0.3 + glob: 7.2.3 + gzip-size: 6.0.0 + lodash: 4.17.21 + open: 7.4.2 + source-map: 0.7.4 + temp: 0.9.4 + yargs: 16.2.0 + dev: false + /[email protected]: resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} engines: {node: '>=0.10.0'} @@ -11593,6 +11619,14 @@ packages: resolution: {integrity: sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==} engines: {node: '>=8'} + /[email protected]: + resolution: {integrity: sha512-yYrrsWnrXMcdsnu/7YMYAofM1ktpL5By7vZhf15CrXijWWrEYZks5AXBudalfSWJLlnen/QUJUB5aoB0kqZUGA==} + engines: {node: '>=6.0.0'} + dependencies: + mkdirp: 0.5.6 + rimraf: 2.6.3 + dev: false + /[email protected]: resolution: {integrity: sha512-G13vtMYPT/J8A4X2SjdtBTphZlrp1gKv6hZiOjw14RCWg6GbHuQBGtjlx75xLbYV/wEc0D7G5K4rxKP/cXk8Bw==} engines: {node: '>=10'} @@ -12184,7 +12218,7 @@ packages: engines: {node: '>=10.13.0'} dependencies: glob-to-regexp: 0.4.1 - graceful-fs: 4.2.10 + graceful-fs: 4.2.11 /[email protected]: resolution: {integrity: sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==} diff --git a/ui/src/components/Comment/index.tsx b/ui/src/components/Comment/index.tsx index be2d5553..81345e7e 100644 --- a/ui/src/components/Comment/index.tsx +++ b/ui/src/components/Comment/index.tsx @@ -23,7 +23,7 @@ import { useTranslation } from 'react-i18next'; import { Link } from 'react-router-dom'; import classNames from 'classnames'; -import { unionBy } from 'lodash'; +import unionBy from 'lodash/unionBy'; import * as Types from '@/common/interface'; import { Modal } from '@/components'; diff --git a/ui/src/components/SchemaForm/index.tsx b/ui/src/components/SchemaForm/index.tsx index 2bb91e31..d0afb692 100644 --- a/ui/src/components/SchemaForm/index.tsx +++ b/ui/src/components/SchemaForm/index.tsx @@ -26,7 +26,7 @@ import React, { import { Form, Button } from 'react-bootstrap'; import { useTranslation } from 'react-i18next'; -import { isEmpty } from 'lodash'; +import isEmpty from 'lodash/isEmpty'; import classnames from 'classnames'; import type * as Type from '@/common/interface'; diff --git a/ui/src/hooks/usePageUsers/index.tsx b/ui/src/hooks/usePageUsers/index.tsx index 9db172da..c0b3836e 100644 --- a/ui/src/hooks/usePageUsers/index.tsx +++ b/ui/src/hooks/usePageUsers/index.tsx @@ -19,7 +19,7 @@ import { useState } from 'react'; -import { uniqBy } from 'lodash'; +import uniqBy from 'lodash/uniqBy'; import * as Types from '@/common/interface'; diff --git a/ui/src/i18n/init.ts b/ui/src/i18n/init.ts index 03f775cb..66d9576e 100644 --- a/ui/src/i18n/init.ts +++ b/ui/src/i18n/init.ts @@ -21,7 +21,7 @@ import { initReactI18next } from 'react-i18next'; import i18next from 'i18next'; import en_US from '@i18n/en_US.yaml'; -import zh_CN from '@i18n/zh_CN.yaml'; +// import zh_CN from '@i18n/zh_CN.yaml'; import { DEFAULT_LANG, LANG_RESOURCE_STORAGE_KEY } from '@/common/constants'; import Storage from '@/utils/storage'; @@ -34,9 +34,9 @@ const initResources = { en_US: { translation: en_US.ui, }, - zh_CN: { - translation: zh_CN.ui, - }, + // zh_CN: { + // translation: zh_CN.ui, + // }, }; const storageLang = Storage.get(LANG_RESOURCE_STORAGE_KEY); diff --git a/ui/src/pages/Admin/index.tsx b/ui/src/pages/Admin/index.tsx index 2ce145f9..b527088f 100644 --- a/ui/src/pages/Admin/index.tsx +++ b/ui/src/pages/Admin/index.tsx @@ -22,7 +22,7 @@ import { Container, Row, Col } from 'react-bootstrap'; import { useTranslation } from 'react-i18next'; import { Outlet, useMatch } from 'react-router-dom'; -import { cloneDeep } from 'lodash'; +import cloneDeep from 'lodash/cloneDeep'; import { usePageTags } from '@/hooks'; import { AccordionNav } from '@/components'; diff --git a/ui/src/pages/Questions/Ask/index.tsx b/ui/src/pages/Questions/Ask/index.tsx index 165e061a..9a1ff14a 100644 --- a/ui/src/pages/Questions/Ask/index.tsx +++ b/ui/src/pages/Questions/Ask/index.tsx @@ -24,7 +24,8 @@ import { useTranslation } from 'react-i18next'; import dayjs from 'dayjs'; import classNames from 'classnames'; -import { isEqual, debounce } from 'lodash'; +import isEqual from 'lodash/isEqual'; +import debounce from 'lodash/debounce'; import { usePageTags, usePromptWithUnload, useCaptchaModal } from '@/hooks'; import { Editor, EditorRef, TagSelector } from '@/components'; diff --git a/ui/src/pages/Users/Notifications/components/Achievements/index.tsx b/ui/src/pages/Users/Notifications/components/Achievements/index.tsx index d8a96ab3..5f2e8f58 100644 --- a/ui/src/pages/Users/Notifications/components/Achievements/index.tsx +++ b/ui/src/pages/Users/Notifications/components/Achievements/index.tsx @@ -21,7 +21,7 @@ import { ListGroup } from 'react-bootstrap'; import { Link } from 'react-router-dom'; import classNames from 'classnames'; -import { isEmpty } from 'lodash'; +import isEmpty from 'lodash/isEmpty'; import { Empty } from '@/components'; diff --git a/ui/src/pages/Users/Notifications/components/Inbox/index.tsx b/ui/src/pages/Users/Notifications/components/Inbox/index.tsx index 6e6e5c2f..64a2c34b 100644 --- a/ui/src/pages/Users/Notifications/components/Inbox/index.tsx +++ b/ui/src/pages/Users/Notifications/components/Inbox/index.tsx @@ -22,7 +22,7 @@ import { Link } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; import classNames from 'classnames'; -import { isEmpty } from 'lodash'; +import isEmpty from 'lodash/isEmpty'; import { FormatTime, Empty } from '@/components'; diff --git a/ui/src/utils/common.ts b/ui/src/utils/common.ts index 8458afd1..13644cd0 100644 --- a/ui/src/utils/common.ts +++ b/ui/src/utils/common.ts @@ -175,8 +175,6 @@ function escapeHtml(str: string) { return str.replace(/[&<>"'`]/g, (tag) => tagsToReplace[tag] || tag); } -const Diff = require('diff'); - function diffText(newText: string, oldText?: string): string { if (!newText) { return ''; @@ -185,28 +183,31 @@ function diffText(newText: string, oldText?: string): string { if (typeof oldText !== 'string') { return escapeHtml(newText); } - const diff = Diff.diffChars(escapeHtml(oldText), escapeHtml(newText)); - const result = diff.map((part) => { - if (part.added) { - if (part.value.replace(/\n/g, '').length <= 0) { - return `<span class="review-text-add d-block">${part.value.replace( - /\n/g, - '↵\n', - )}</span>`; + let result = []; + import('diff').then((Diff) => { + const diff = Diff.diffChars(escapeHtml(oldText), escapeHtml(newText)); + result = diff.map((part) => { + if (part.added) { + if (part.value.replace(/\n/g, '').length <= 0) { + return `<span class="review-text-add d-block">${part.value.replace( + /\n/g, + '↵\n', + )}</span>`; + } + return `<span class="review-text-add">${part.value}</span>`; } - return `<span class="review-text-add">${part.value}</span>`; - } - if (part.removed) { - if (part.value.replace(/\n/g, '').length <= 0) { - return `<span class="review-text-delete text-decoration-none d-block">${part.value.replace( - /\n/g, - '↵\n', - )}</span>`; + if (part.removed) { + if (part.value.replace(/\n/g, '').length <= 0) { + return `<span class="review-text-delete text-decoration-none d-block">${part.value.replace( + /\n/g, + '↵\n', + )}</span>`; + } + return `<span class="review-text-delete">${part.value}</span>`; } - return `<span class="review-text-delete">${part.value}</span>`; - } - return part.value; + return part.value; + }); }); return result.join(''); diff --git a/ui/src/utils/saveDraft.ts b/ui/src/utils/saveDraft.ts index e2dd7c17..6d7f1814 100644 --- a/ui/src/utils/saveDraft.ts +++ b/ui/src/utils/saveDraft.ts @@ -17,7 +17,7 @@ * under the License. */ -import { debounce } from 'lodash'; +import debounce from 'lodash/debounce'; import { DRAFT_QUESTION_STORAGE_KEY,
