├── .browserslistrc
├── .eslintignore
├── .eslintrc.js
├── .gitignore
├── .husky
├── .gitignore
└── pre-commit
├── .npmrc
├── .prettierrc
├── .stylelintrc.json
├── README.md
├── babel.config.js
├── build
├── index.html
└── static
│ ├── css
│ └── main-style.da4059.css
│ ├── dll
│ ├── core-js@3.15.1.production.js
│ ├── dll_basic_cfedf4.production.js
│ ├── dll_basic_cfedf4.production.js.VERSION.txt
│ ├── dll_tool_441c03.production.js
│ └── dll_tool_441c03.production.js.VERSION.txt
│ └── js
│ ├── main.f961ed.js
│ └── main.f961ed.js.LICENSE.txt
├── dll
├── basic_manifest_development.json
├── basic_manifest_production.json
├── dll_basic_cfedf4.production.js
├── dll_basic_cfedf4.production.js.VERSION.txt
├── dll_basic_e0cff6.development.js
├── dll_basic_e0cff6.development.js.map
├── dll_tool_441c03.production.js
├── dll_tool_441c03.production.js.VERSION.txt
├── dll_tool_9f2285.development.js
├── dll_tool_9f2285.development.js.map
├── tool_manifest_development.json
└── tool_manifest_production.json
├── lint-staged.config.js
├── package.json
├── postcss.config.js
├── report
└── dll
│ ├── report.html
│ └── stats.json
├── scripts
├── build.js
├── config
│ ├── devServer.config.js
│ ├── htmlPlugins.config.js
│ ├── loaders.config.js
│ ├── paths.config.js
│ ├── webpack.base.config.js
│ ├── webpack.dev.config.js
│ ├── webpack.dll.config.js
│ └── webpack.prod.config.js
├── dll-version-check.js
├── dll.js
├── start.js
└── utils
│ ├── findDLLFile.js
│ ├── parseCommandLine.js
│ └── tools.js
├── src
├── bootstrap.tsx
├── components
│ └── DynamicSystem
│ │ └── index.tsx
├── index.html
├── index.tsx
├── modules
│ ├── remote
│ │ ├── Cache.tsx
│ │ ├── Content.tsx
│ │ ├── index.tsx
│ │ └── remoteSlice.ts
│ └── root
│ │ ├── routes.tsx
│ │ └── styles
│ │ └── root.scss
└── store
│ ├── StoreNames.ts
│ ├── createSlice.ts
│ ├── createStore.ts
│ ├── index.ts
│ └── initImmer.ts
├── tsconfig.json
├── tsconfig.prod.json
├── tsconfig.tsbuildinfo
├── typings
├── global.d.ts
└── media.d.ts
└── yarn.lock
/.browserslistrc:
--------------------------------------------------------------------------------
1 | # Browsers that we support
2 |
3 | >0.1%
4 | last 4 versions
5 | Firefox ESR
6 | not ie <= 8
7 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | scripts/*
2 | node_modules/**/*
3 | .eslintrc.js
4 | lint-staged.config.js
5 | babel.config.js
6 | typings/*
7 | dll/*
8 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | // 仅 commit 时会用
2 | const commitRules = {
3 | 'no-alert': 2,
4 | 'no-debugger': 2,
5 | 'no-console': [
6 | 'error',
7 | {
8 | allow: ['warn', 'error'],
9 | },
10 | ],
11 | 'no-unused-vars': 2,
12 | };
13 |
14 | module.exports = {
15 | root: true,
16 | extends: [
17 | 'airbnb-typescript',
18 | 'plugin:@typescript-eslint/recommended',
19 | 'plugin:prettier/recommended',
20 | 'prettier',
21 | ],
22 | parserOptions: {
23 | project: './tsconfig.json',
24 | ecmaVersion: 6,
25 | sourceType: 'module',
26 | ecmaFeatures: {
27 | jsx: true,
28 | },
29 | },
30 | globals: {
31 | React: true,
32 | ReactDOM: true,
33 | _: true,
34 | moment: true,
35 | mobx: true
36 | },
37 | rules: {
38 | // javascript
39 | 'brace-style': [2, '1tbs', { allowSingleLine: true }],
40 | 'block-spacing': [2, 'always'],
41 | 'no-const-assign': 2,
42 | 'prefer-destructuring': 0, // 推荐通过结构赋值访问 object 或者 array
43 | 'no-prototype-builtins': 0,
44 | 'no-useless-escape': 0,
45 | 'no-unused-expressions': 2, // 开启对短路求值和三元表达式的支持
46 | 'no-console': [2, { allow: ['warn', 'error', 'log'] }],
47 | 'no-nested-ternary': 2, // 禁止三元表达式嵌套
48 | 'no-param-reassign': 0, // 禁止对函数参数再赋值,immer 需要打开
49 | // jsx
50 | 'jsx-a11y/anchor-is-valid': 0,
51 | 'jsx-a11y/click-events-have-key-events': 0, // 强制 绑定 onClick 事件同时也绑定 onKeyUp, onKeyDown, onKeyPress 等事件
52 | 'jsx-a11y/no-static-element-interactions': 0, // 强制给 div span 等没有语义的标签加上 role 角色,(在有onClick 等事件的前提下)
53 | // react
54 | '@typescript-eslint/no-unused-expressions': 2, // 开启对短路求值和三元表达式的支持
55 | 'react/jsx-no-undef': [
56 | 2,
57 | {
58 | allowGlobals: true,
59 | },
60 | ],
61 | 'react/static-property-placement': 0, // static 静态类型强制定义在class 组件外
62 | 'react/no-deprecated': 0,
63 | 'react/jsx-no-target-blank': 0,
64 | 'react/jsx-filename-extension': [1, { extensions: ['.js', '.jsx', '.ts', '.tsx'] }], // 识别扩展名
65 | 'react/jsx-props-no-spreading': 0, // 禁止 jsx 组件上使用
66 | 'react/no-array-index-key': 2, // 禁止使用遍历中的 index 作为 key, 通过重新命名变量避开 const count = idx;
67 | 'react/require-default-props': 0, // 强制给 默认值
68 | 'import/no-extraneous-dependencies': 0, // import 的内容要在 package.json 的 dependencies下(关闭)
69 | /*
70 | * 1. 循环引用检查, 运行时开销很大
71 | * https://github.com/benmosher/eslint-plugin-import/blob/d81f48a2506182738409805f5272eff4d77c9348/docs/rules/no-cycle.md
72 | * */
73 | 'import/no-cycle': 'off',
74 | /*
75 | * 2. 用来检查未使用的模块或者代码,会导致控制台频繁打印error
76 | * https://github.com/benmosher/eslint-plugin-import/blob/f63dd261809de6883b13b6b5b960e6d7f42a7813/docs/rules/no-unused-modules.md
77 | * */
78 | 'import/no-unused-modules': 'off',
79 | '@typescript-eslint/camelcase': 0,
80 | '@typescript-eslint/lines-between-class-members': [
81 | 2,
82 | 'always',
83 | {
84 | exceptAfterSingleLine: true, // 单行的类成员跳过检查
85 | exceptAfterOverload: true, // 重载的跳过检查
86 | },
87 | ],
88 | '@typescript-eslint/naming-convention': [
89 | 2,
90 | { selector: 'variable', format: ['camelCase', 'PascalCase', 'UPPER_CASE'] },
91 | { selector: 'function', format: ['camelCase', 'PascalCase'] },
92 | { selector: 'typeLike', format: ['PascalCase'] },
93 | { selector: 'enumMember', format: ['UPPER_CASE', 'camelCase', 'PascalCase'] },
94 | { selector: 'enum', format: ['UPPER_CASE', 'PascalCase'] },
95 | ],
96 | 'prettier/prettier': [
97 | 'error',
98 | {},
99 | {
100 | fileInfoOptions: {
101 | withNodeModules: false,
102 | },
103 | },
104 | ],
105 | // NOTICE: 因为测试暂时关闭检查,
106 | // ...(process.env.ESLINT_ENV === 'commit' ? commitRules : {}),
107 | },
108 | env: {
109 | browser: true,
110 | node: true,
111 | },
112 | settings: {
113 | react: {
114 | version: require('./package.json').dependencies.react,
115 | },
116 | },
117 | };
118 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules/
3 | npm-debug.log*
4 | yarn-debug.log*
5 | yarn-error.log*
6 |
7 | # Editor directories and files
8 | .idea
9 | .vscode
10 | *.suo
11 | *.ntvs*
12 | *.njsproj
13 | *.sln
14 | .tags*
15 |
16 | # cache
17 | tsconfig.prod.tsbuildinfo
18 |
19 | # husky
20 | ./.husky/_
--------------------------------------------------------------------------------
/.husky/.gitignore:
--------------------------------------------------------------------------------
1 | _
2 |
--------------------------------------------------------------------------------
/.husky/pre-commit:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | . "$(dirname "$0")/_/husky.sh"
3 |
4 | npm run lint-staged
5 |
--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 | registry=https://registry.npm.taobao.org
2 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "printWidth": 100,
3 | "singleQuote": true,
4 | "trailingComma": "all",
5 | "arrowParens": "always",
6 | "semi": true,
7 | "tabWidth": 2
8 | }
9 |
--------------------------------------------------------------------------------
/.stylelintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": [
3 | "stylelint-config-standard",
4 | "stylelint-config-prettier"
5 | ],
6 | "plugins": [
7 | "stylelint-prettier",
8 | "stylelint-order"
9 | ],
10 | "rules": {
11 | "prettier/prettier": true,
12 | "max-nesting-depth": 4,
13 | "order/order": [
14 | ["custom-properties", "declarations"], {
15 | "disableFix": true
16 | }
17 | ],
18 | "order/properties-order": [
19 | "position",
20 | "top",
21 | "right",
22 | "bottom",
23 | "left",
24 | "z-index",
25 | "display",
26 | "float",
27 | "width",
28 | "height",
29 | "max-width",
30 | "max-height",
31 | "min-width",
32 | "min-height",
33 | "padding",
34 | "padding-top",
35 | "padding-right",
36 | "padding-bottom",
37 | "padding-left",
38 | "margin",
39 | "margin-top",
40 | "margin-right",
41 | "margin-bottom",
42 | "margin-left",
43 | "overflow",
44 | "overflow-x",
45 | "overflow-y",
46 | "clear",
47 | "font",
48 | "font-family",
49 | "font-size",
50 | "font-style",
51 | "font-weight",
52 | "line-height",
53 | "letter-spacing",
54 | "word-spacing",
55 | "color",
56 | "text-align",
57 | "text-decoration",
58 | "text-indent",
59 | "text-overflow",
60 | "text-shadow",
61 | "background",
62 | "background-color",
63 | "background-image",
64 | "background-position",
65 | "background-repeat",
66 | "background-size",
67 | "border",
68 | "border-top",
69 | "border-right",
70 | "border-bottom",
71 | "border-left",
72 | "border-color",
73 | "border-image"
74 | ]
75 | },
76 | "ignoreFiles": [
77 | "**/*.html",
78 | "**/*.js",
79 | "**/*.ts",
80 | "**/*.tsx",
81 | "**/*.png",
82 | "**/*.svg",
83 | "**/*.jpg",
84 | "**/*.jpeg",
85 | "**/*.md"
86 | ]
87 | }
88 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # react16-router4-template
2 |
3 | ### 版本
4 |
5 | * master 分支与 v3.0.0 tag 是 webpack 5.x + redux + immer + Typescript 的版本
6 | * webpack-v3-template 分支与 v1.0.0 tag 是 webpack 3.x 的版本
7 | * webpack-v4-template 分支与 v2.0.0 tag 是 webpack 4.x 的版本
8 | * enhance-redux redux 状态管理升级版本
9 | * *最新的构建改为了使用 mobx, 源码参考地址 https://github.com/mjzhang1993/react-mobx-template/tree/master*
10 |
11 | ## 重要文件版本
12 |
13 | > 更多版本信息查看 package.json 文件
14 |
15 |
16 | ## 命令
17 |
18 | #### 0. 安装
19 |
20 | ```bash
21 | yarn install
22 | ```
23 |
24 | #### 1. 打包 DLL 文件
25 |
26 | ```bash
27 | yarn build:dll
28 | ```
29 |
30 | #### 1. 运行开发环境
31 |
32 | ```bash
33 | yarn start
34 | ```
35 |
36 | #### 2. 输出生产环境文件
37 |
38 | ```bash
39 | yarn run build
40 | ```
41 |
42 | #### 3. 输出生产环境,并查看模块分配
43 |
44 | ```bash
45 | yarn run build -- -r
46 | ```
47 |
48 | #### 5. 安装 yarn
49 |
50 | > yarn 是用来代替 npm 的 node 包管理工具, 与 npm 有类似的命令,具体安装方式及使用方法查看 [yarn 命令使用](http://blog.csdn.net/mjzhang1993/article/details/70092902)
51 |
52 | ## 项目相关文章
53 |
54 | * [React - Webpack 开发环境重新搭建](http://blog.csdn.net/mjzhang1993/article/details/79013430)
55 | * [重新搭建 React - Redux - Router 完整项目](http://blog.csdn.net/mjzhang1993/article/details/79022633)
56 | * [React-router-v4 - Webpack 实现按需加载(code-splitting)](http://blog.csdn.net/mjzhang1993/article/details/79094594)
57 | * [使用 Immer 代替 immutable 在 react 项目中实现不可变数据](https://blog.csdn.net/mjzhang1993/article/details/117084495)
58 |
59 | ## 目录结构说明
60 |
61 | ```bash
62 | .
63 | ├── README.md
64 | ├── babel.config.js
65 | ├── build # 构建结果
66 | ├── dll # 生成的 dll
67 | ├── lint-staged.config.js
68 | ├── report # 打包结果
69 | ├── scripts # 构建相关脚本
70 | │ ├── build.js
71 | │ ├── config
72 | │ ├── dll-version-check.js
73 | │ ├── dll.js
74 | │ ├── start.js
75 | │ └── utils
76 | ├── src
77 | │ ├── bootstrap.tsx # 启动文件
78 | │ ├── index.html
79 | │ ├── index.tsx # 入口文件
80 | │ └── store # store 相关封装
81 | │ ├── StoreNames.ts
82 | │ ├── createSlice.ts
83 | │ ├── createStore.ts
84 | │ ├── index.ts # store 对接入口
85 | │ └── initImmer.ts
86 | │ ├── modules # 业务模块
87 | │ │ ├── remote
88 | │ │ └── root
89 | │ ├── components # 抽象的组件
90 | │ │ └── DynamicSystem
91 | ├── tsconfig.json
92 | ├── tsconfig.prod.json
93 | ├── typings
94 | └── yarn.lock
95 | ```
96 |
97 |
98 |
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = function (api) {
2 | api.cache(true);
3 |
4 | const presets = [
5 | [
6 | '@babel/preset-env',
7 | {
8 | modules: false,
9 | loose: true,
10 | bugfixes: true,
11 | useBuiltIns: false,
12 | },
13 | ],
14 | [
15 | '@babel/preset-react',
16 | {
17 | runtime: 'classic',
18 | },
19 | ],
20 | '@babel/preset-typescript',
21 | ];
22 | const plugins = [
23 | ['@babel/plugin-proposal-decorators', { decoratorsBeforeExport: true }],
24 | ['@babel/plugin-proposal-class-properties', {loose: true}],
25 | '@babel/plugin-proposal-export-default-from',
26 | '@babel/plugin-proposal-function-sent',
27 | '@babel/plugin-proposal-export-namespace-from',
28 | '@babel/plugin-syntax-dynamic-import',
29 | ['@babel/plugin-transform-classes', { loose: true }],
30 | ['@babel/plugin-transform-runtime', { corejs: false, helpers: true, regenerator: true }],
31 | ['import', { libraryName: 'antd', libraryDirectory: 'es', style: 'css' }, 'antd'],
32 | ];
33 |
34 | return { presets, plugins, ignore: [/[\/\\]core-js/, /@babel[\/\\]runtime/]};
35 | };
36 |
--------------------------------------------------------------------------------
/build/index.html:
--------------------------------------------------------------------------------
1 |
title
--------------------------------------------------------------------------------
/build/static/dll/dll_basic_cfedf4.production.js.VERSION.txt:
--------------------------------------------------------------------------------
1 | {
2 | "react": "^17.0.2",
3 | "react-dom": "^17.0.2"
4 | }
--------------------------------------------------------------------------------
/build/static/dll/dll_tool_441c03.production.js:
--------------------------------------------------------------------------------
1 | var dll_tool;!function(){var n={"./node_modules/axios/index.js":function(n,t,r){n.exports=r("./node_modules/axios/lib/axios.js")},"./node_modules/axios/lib/adapters/xhr.js":function(n,t,r){"use strict";var e=r("./node_modules/axios/lib/utils.js"),u=r("./node_modules/axios/lib/core/settle.js"),o=r("./node_modules/axios/lib/helpers/cookies.js"),i=r("./node_modules/axios/lib/helpers/buildURL.js"),a=r("./node_modules/axios/lib/core/buildFullPath.js"),f=r("./node_modules/axios/lib/helpers/parseHeaders.js"),c=r("./node_modules/axios/lib/helpers/isURLSameOrigin.js"),s=r("./node_modules/axios/lib/core/createError.js");n.exports=function(n){return new Promise((function(t,r){var l=n.data,p=n.headers;e.isFormData(l)&&delete p["Content-Type"];var h=new XMLHttpRequest;if(n.auth){var d=n.auth.username||"",v=n.auth.password?unescape(encodeURIComponent(n.auth.password)):"";p.Authorization="Basic "+btoa(d+":"+v)}var _=a(n.baseURL,n.url);if(h.open(n.method.toUpperCase(),i(_,n.params,n.paramsSerializer),!0),h.timeout=n.timeout,h.onreadystatechange=function(){if(h&&4===h.readyState&&(0!==h.status||h.responseURL&&0===h.responseURL.indexOf("file:"))){var e="getAllResponseHeaders"in h?f(h.getAllResponseHeaders()):null,o={data:n.responseType&&"text"!==n.responseType?h.response:h.responseText,status:h.status,statusText:h.statusText,headers:e,config:n,request:h};u(t,r,o),h=null}},h.onabort=function(){h&&(r(s("Request aborted",n,"ECONNABORTED",h)),h=null)},h.onerror=function(){r(s("Network Error",n,null,h)),h=null},h.ontimeout=function(){var t="timeout of "+n.timeout+"ms exceeded";n.timeoutErrorMessage&&(t=n.timeoutErrorMessage),r(s(t,n,"ECONNABORTED",h)),h=null},e.isStandardBrowserEnv()){var g=(n.withCredentials||c(_))&&n.xsrfCookieName?o.read(n.xsrfCookieName):void 0;g&&(p[n.xsrfHeaderName]=g)}if("setRequestHeader"in h&&e.forEach(p,(function(n,t){void 0===l&&"content-type"===t.toLowerCase()?delete p[t]:h.setRequestHeader(t,n)})),e.isUndefined(n.withCredentials)||(h.withCredentials=!!n.withCredentials),n.responseType)try{h.responseType=n.responseType}catch(t){if("json"!==n.responseType)throw t}"function"==typeof n.onDownloadProgress&&h.addEventListener("progress",n.onDownloadProgress),"function"==typeof n.onUploadProgress&&h.upload&&h.upload.addEventListener("progress",n.onUploadProgress),n.cancelToken&&n.cancelToken.promise.then((function(n){h&&(h.abort(),r(n),h=null)})),l||(l=null),h.send(l)}))}},"./node_modules/axios/lib/axios.js":function(n,t,r){"use strict";var e=r("./node_modules/axios/lib/utils.js"),u=r("./node_modules/axios/lib/helpers/bind.js"),o=r("./node_modules/axios/lib/core/Axios.js"),i=r("./node_modules/axios/lib/core/mergeConfig.js");function a(n){var t=new o(n),r=u(o.prototype.request,t);return e.extend(r,o.prototype,t),e.extend(r,t),r}var f=a(r("./node_modules/axios/lib/defaults.js"));f.Axios=o,f.create=function(n){return a(i(f.defaults,n))},f.Cancel=r("./node_modules/axios/lib/cancel/Cancel.js"),f.CancelToken=r("./node_modules/axios/lib/cancel/CancelToken.js"),f.isCancel=r("./node_modules/axios/lib/cancel/isCancel.js"),f.all=function(n){return Promise.all(n)},f.spread=r("./node_modules/axios/lib/helpers/spread.js"),f.isAxiosError=r("./node_modules/axios/lib/helpers/isAxiosError.js"),n.exports=f,n.exports.default=f},"./node_modules/axios/lib/cancel/Cancel.js":function(n){"use strict";function t(n){this.message=n}t.prototype.toString=function(){return"Cancel"+(this.message?": "+this.message:"")},t.prototype.__CANCEL__=!0,n.exports=t},"./node_modules/axios/lib/cancel/CancelToken.js":function(n,t,r){"use strict";var e=r("./node_modules/axios/lib/cancel/Cancel.js");function u(n){if("function"!=typeof n)throw new TypeError("executor must be a function.");var t;this.promise=new Promise((function(n){t=n}));var r=this;n((function(n){r.reason||(r.reason=new e(n),t(r.reason))}))}u.prototype.throwIfRequested=function(){if(this.reason)throw this.reason},u.source=function(){var n;return{token:new u((function(t){n=t})),cancel:n}},n.exports=u},"./node_modules/axios/lib/cancel/isCancel.js":function(n){"use strict";n.exports=function(n){return!(!n||!n.__CANCEL__)}},"./node_modules/axios/lib/core/Axios.js":function(n,t,r){"use strict";var e=r("./node_modules/axios/lib/utils.js"),u=r("./node_modules/axios/lib/helpers/buildURL.js"),o=r("./node_modules/axios/lib/core/InterceptorManager.js"),i=r("./node_modules/axios/lib/core/dispatchRequest.js"),a=r("./node_modules/axios/lib/core/mergeConfig.js");function f(n){this.defaults=n,this.interceptors={request:new o,response:new o}}f.prototype.request=function(n){"string"==typeof n?(n=arguments[1]||{}).url=arguments[0]:n=n||{},(n=a(this.defaults,n)).method?n.method=n.method.toLowerCase():this.defaults.method?n.method=this.defaults.method.toLowerCase():n.method="get";var t=[i,void 0],r=Promise.resolve(n);for(this.interceptors.request.forEach((function(n){t.unshift(n.fulfilled,n.rejected)})),this.interceptors.response.forEach((function(n){t.push(n.fulfilled,n.rejected)}));t.length;)r=r.then(t.shift(),t.shift());return r},f.prototype.getUri=function(n){return n=a(this.defaults,n),u(n.url,n.params,n.paramsSerializer).replace(/^\?/,"")},e.forEach(["delete","get","head","options"],(function(n){f.prototype[n]=function(t,r){return this.request(a(r||{},{method:n,url:t,data:(r||{}).data}))}})),e.forEach(["post","put","patch"],(function(n){f.prototype[n]=function(t,r,e){return this.request(a(e||{},{method:n,url:t,data:r}))}})),n.exports=f},"./node_modules/axios/lib/core/InterceptorManager.js":function(n,t,r){"use strict";var e=r("./node_modules/axios/lib/utils.js");function u(){this.handlers=[]}u.prototype.use=function(n,t){return this.handlers.push({fulfilled:n,rejected:t}),this.handlers.length-1},u.prototype.eject=function(n){this.handlers[n]&&(this.handlers[n]=null)},u.prototype.forEach=function(n){e.forEach(this.handlers,(function(t){null!==t&&n(t)}))},n.exports=u},"./node_modules/axios/lib/core/buildFullPath.js":function(n,t,r){"use strict";var e=r("./node_modules/axios/lib/helpers/isAbsoluteURL.js"),u=r("./node_modules/axios/lib/helpers/combineURLs.js");n.exports=function(n,t){return n&&!e(t)?u(n,t):t}},"./node_modules/axios/lib/core/createError.js":function(n,t,r){"use strict";var e=r("./node_modules/axios/lib/core/enhanceError.js");n.exports=function(n,t,r,u,o){var i=new Error(n);return e(i,t,r,u,o)}},"./node_modules/axios/lib/core/dispatchRequest.js":function(n,t,r){"use strict";var e=r("./node_modules/axios/lib/utils.js"),u=r("./node_modules/axios/lib/core/transformData.js"),o=r("./node_modules/axios/lib/cancel/isCancel.js"),i=r("./node_modules/axios/lib/defaults.js");function a(n){n.cancelToken&&n.cancelToken.throwIfRequested()}n.exports=function(n){return a(n),n.headers=n.headers||{},n.data=u(n.data,n.headers,n.transformRequest),n.headers=e.merge(n.headers.common||{},n.headers[n.method]||{},n.headers),e.forEach(["delete","get","head","post","put","patch","common"],(function(t){delete n.headers[t]})),(n.adapter||i.adapter)(n).then((function(t){return a(n),t.data=u(t.data,t.headers,n.transformResponse),t}),(function(t){return o(t)||(a(n),t&&t.response&&(t.response.data=u(t.response.data,t.response.headers,n.transformResponse))),Promise.reject(t)}))}},"./node_modules/axios/lib/core/enhanceError.js":function(n){"use strict";n.exports=function(n,t,r,e,u){return n.config=t,r&&(n.code=r),n.request=e,n.response=u,n.isAxiosError=!0,n.toJSON=function(){return{message:this.message,name:this.name,description:this.description,number:this.number,fileName:this.fileName,lineNumber:this.lineNumber,columnNumber:this.columnNumber,stack:this.stack,config:this.config,code:this.code}},n}},"./node_modules/axios/lib/core/mergeConfig.js":function(n,t,r){"use strict";var e=r("./node_modules/axios/lib/utils.js");n.exports=function(n,t){t=t||{};var r={},u=["url","method","data"],o=["headers","auth","proxy","params"],i=["baseURL","transformRequest","transformResponse","paramsSerializer","timeout","timeoutMessage","withCredentials","adapter","responseType","xsrfCookieName","xsrfHeaderName","onUploadProgress","onDownloadProgress","decompress","maxContentLength","maxBodyLength","maxRedirects","transport","httpAgent","httpsAgent","cancelToken","socketPath","responseEncoding"],a=["validateStatus"];function f(n,t){return e.isPlainObject(n)&&e.isPlainObject(t)?e.merge(n,t):e.isPlainObject(t)?e.merge({},t):e.isArray(t)?t.slice():t}function c(u){e.isUndefined(t[u])?e.isUndefined(n[u])||(r[u]=f(void 0,n[u])):r[u]=f(n[u],t[u])}e.forEach(u,(function(n){e.isUndefined(t[n])||(r[n]=f(void 0,t[n]))})),e.forEach(o,c),e.forEach(i,(function(u){e.isUndefined(t[u])?e.isUndefined(n[u])||(r[u]=f(void 0,n[u])):r[u]=f(void 0,t[u])})),e.forEach(a,(function(e){e in t?r[e]=f(n[e],t[e]):e in n&&(r[e]=f(void 0,n[e]))}));var s=u.concat(o).concat(i).concat(a),l=Object.keys(n).concat(Object.keys(t)).filter((function(n){return-1===s.indexOf(n)}));return e.forEach(l,c),r}},"./node_modules/axios/lib/core/settle.js":function(n,t,r){"use strict";var e=r("./node_modules/axios/lib/core/createError.js");n.exports=function(n,t,r){var u=r.config.validateStatus;r.status&&u&&!u(r.status)?t(e("Request failed with status code "+r.status,r.config,null,r.request,r)):n(r)}},"./node_modules/axios/lib/core/transformData.js":function(n,t,r){"use strict";var e=r("./node_modules/axios/lib/utils.js");n.exports=function(n,t,r){return e.forEach(r,(function(r){n=r(n,t)})),n}},"./node_modules/axios/lib/defaults.js":function(n,t,r){"use strict";var e=r("./node_modules/axios/lib/utils.js"),u=r("./node_modules/axios/lib/helpers/normalizeHeaderName.js"),o={"Content-Type":"application/x-www-form-urlencoded"};function i(n,t){!e.isUndefined(n)&&e.isUndefined(n["Content-Type"])&&(n["Content-Type"]=t)}var a,f={adapter:(("undefined"!=typeof XMLHttpRequest||"undefined"!=typeof process&&"[object process]"===Object.prototype.toString.call(process))&&(a=r("./node_modules/axios/lib/adapters/xhr.js")),a),transformRequest:[function(n,t){return u(t,"Accept"),u(t,"Content-Type"),e.isFormData(n)||e.isArrayBuffer(n)||e.isBuffer(n)||e.isStream(n)||e.isFile(n)||e.isBlob(n)?n:e.isArrayBufferView(n)?n.buffer:e.isURLSearchParams(n)?(i(t,"application/x-www-form-urlencoded;charset=utf-8"),n.toString()):e.isObject(n)?(i(t,"application/json;charset=utf-8"),JSON.stringify(n)):n}],transformResponse:[function(n){if("string"==typeof n)try{n=JSON.parse(n)}catch(n){}return n}],timeout:0,xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN",maxContentLength:-1,maxBodyLength:-1,validateStatus:function(n){return n>=200&&n<300},headers:{common:{Accept:"application/json, text/plain, */*"}}};e.forEach(["delete","get","head"],(function(n){f.headers[n]={}})),e.forEach(["post","put","patch"],(function(n){f.headers[n]=e.merge(o)})),n.exports=f},"./node_modules/axios/lib/helpers/bind.js":function(n){"use strict";n.exports=function(n,t){return function(){for(var r=new Array(arguments.length),e=0;e=0)return;i[t]="set-cookie"===t?(i[t]?i[t]:[]).concat([r]):i[t]?i[t]+", "+r:r}})),i):i}},"./node_modules/axios/lib/helpers/spread.js":function(n){"use strict";n.exports=function(n){return function(t){return n.apply(null,t)}}},"./node_modules/axios/lib/utils.js":function(n,t,r){"use strict";var e=r("./node_modules/axios/lib/helpers/bind.js"),u=Object.prototype.toString;function o(n){return"[object Array]"===u.call(n)}function i(n){return void 0===n}function a(n){return null!==n&&"object"==typeof n}function f(n){if("[object Object]"!==u.call(n))return!1;var t=Object.getPrototypeOf(n);return null===t||t===Object.prototype}function c(n){return"[object Function]"===u.call(n)}function s(n,t){if(null!=n)if("object"!=typeof n&&(n=[n]),o(n))for(var r=0,e=n.length;r"']/g,Z=RegExp(H.source),K=RegExp(V.source),J=/<%-([\s\S]+?)%>/g,G=/<%([\s\S]+?)%>/g,X=/<%=([\s\S]+?)%>/g,Y=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,Q=/^\w*$/,nn=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,tn=/[\\^$.*+?()[\]{}|]/g,rn=RegExp(tn.source),en=/^\s+/,un=/\s/,on=/\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/,an=/\{\n\/\* \[wrapped with (.+)\] \*/,fn=/,? & /,cn=/[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g,sn=/[()=,{}\[\]\/\s]/,ln=/\\(\\)?/g,pn=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,hn=/\w*$/,dn=/^[-+]0x[0-9a-f]+$/i,vn=/^0b[01]+$/i,_n=/^\[object .+?Constructor\]$/,gn=/^0o[0-7]+$/i,yn=/^(?:0|[1-9]\d*)$/,mn=/[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g,bn=/($^)/,xn=/['\n\r\u2028\u2029\\]/g,wn="\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff",jn="a-z\\xdf-\\xf6\\xf8-\\xff",An="A-Z\\xc0-\\xd6\\xd8-\\xde",En="\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000",Rn="["+En+"]",On="["+wn+"]",Sn="\\d+",Cn="["+jn+"]",kn="[^\\ud800-\\udfff"+En+Sn+"\\u2700-\\u27bf"+jn+An+"]",Un="\\ud83c[\\udffb-\\udfff]",Ln="[^\\ud800-\\udfff]",In="(?:\\ud83c[\\udde6-\\uddff]){2}",Tn="[\\ud800-\\udbff][\\udc00-\\udfff]",zn="["+An+"]",Bn="(?:"+Cn+"|"+kn+")",Nn="(?:"+zn+"|"+kn+")",Dn="(?:['’](?:d|ll|m|re|s|t|ve))?",Pn="(?:['’](?:D|LL|M|RE|S|T|VE))?",Wn="(?:"+On+"|"+Un+")?",qn="[\\ufe0e\\ufe0f]?",Fn=qn+Wn+"(?:\\u200d(?:"+[Ln,In,Tn].join("|")+")"+qn+Wn+")*",$n="(?:"+["[\\u2700-\\u27bf]",In,Tn].join("|")+")"+Fn,Mn="(?:"+[Ln+On+"?",On,In,Tn,"[\\ud800-\\udfff]"].join("|")+")",Hn=RegExp("['’]","g"),Vn=RegExp(On,"g"),Zn=RegExp(Un+"(?="+Un+")|"+Mn+Fn,"g"),Kn=RegExp([zn+"?"+Cn+"+"+Dn+"(?="+[Rn,zn,"$"].join("|")+")",Nn+"+"+Pn+"(?="+[Rn,zn+Bn,"$"].join("|")+")",zn+"?"+Bn+"+"+Dn,zn+"+"+Pn,"\\d*(?:1ST|2ND|3RD|(?![123])\\dTH)(?=\\b|[a-z_])","\\d*(?:1st|2nd|3rd|(?![123])\\dth)(?=\\b|[A-Z_])",Sn,$n].join("|"),"g"),Jn=RegExp("[\\u200d\\ud800-\\udfff"+wn+"\\ufe0e\\ufe0f]"),Gn=/[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/,Xn=["Array","Buffer","DataView","Date","Error","Float32Array","Float64Array","Function","Int8Array","Int16Array","Int32Array","Map","Math","Object","Promise","RegExp","Set","String","Symbol","TypeError","Uint8Array","Uint8ClampedArray","Uint16Array","Uint32Array","WeakMap","_","clearTimeout","isFinite","parseInt","setTimeout"],Yn=-1,Qn={};Qn[I]=Qn[T]=Qn[z]=Qn[B]=Qn[N]=Qn[D]=Qn[P]=Qn[W]=Qn[q]=!0,Qn[v]=Qn[_]=Qn[U]=Qn[g]=Qn[L]=Qn[y]=Qn[m]=Qn[b]=Qn[w]=Qn[j]=Qn[A]=Qn[R]=Qn[O]=Qn[S]=Qn[k]=!1;var nt={};nt[v]=nt[_]=nt[U]=nt[L]=nt[g]=nt[y]=nt[I]=nt[T]=nt[z]=nt[B]=nt[N]=nt[w]=nt[j]=nt[A]=nt[R]=nt[O]=nt[S]=nt[C]=nt[D]=nt[P]=nt[W]=nt[q]=!0,nt[m]=nt[b]=nt[k]=!1;var tt={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},rt=parseFloat,et=parseInt,ut="object"==typeof r.g&&r.g&&r.g.Object===Object&&r.g,ot="object"==typeof self&&self&&self.Object===Object&&self,it=ut||ot||Function("return this")(),at=t&&!t.nodeType&&t,ft=at&&n&&!n.nodeType&&n,ct=ft&&ft.exports===at,st=ct&&ut.process,lt=function(){try{return ft&&ft.require&&ft.require("util").types||st&&st.binding&&st.binding("util")}catch(n){}}(),pt=lt&<.isArrayBuffer,ht=lt&<.isDate,dt=lt&<.isMap,vt=lt&<.isRegExp,_t=lt&<.isSet,gt=lt&<.isTypedArray;function yt(n,t,r){switch(r.length){case 0:return n.call(t);case 1:return n.call(t,r[0]);case 2:return n.call(t,r[0],r[1]);case 3:return n.call(t,r[0],r[1],r[2])}return n.apply(t,r)}function mt(n,t,r,e){for(var u=-1,o=null==n?0:n.length;++u-1}function Et(n,t,r){for(var e=-1,u=null==n?0:n.length;++e-1;);return r}function Kt(n,t){for(var r=n.length;r--&&Tt(t,n[r],0)>-1;);return r}function Jt(n,t){for(var r=n.length,e=0;r--;)n[r]===t&&++e;return e}var Gt=Pt({"À":"A","Á":"A","Â":"A","Ã":"A","Ä":"A","Å":"A","à":"a","á":"a","â":"a","ã":"a","ä":"a","å":"a","Ç":"C","ç":"c","Ð":"D","ð":"d","È":"E","É":"E","Ê":"E","Ë":"E","è":"e","é":"e","ê":"e","ë":"e","Ì":"I","Í":"I","Î":"I","Ï":"I","ì":"i","í":"i","î":"i","ï":"i","Ñ":"N","ñ":"n","Ò":"O","Ó":"O","Ô":"O","Õ":"O","Ö":"O","Ø":"O","ò":"o","ó":"o","ô":"o","õ":"o","ö":"o","ø":"o","Ù":"U","Ú":"U","Û":"U","Ü":"U","ù":"u","ú":"u","û":"u","ü":"u","Ý":"Y","ý":"y","ÿ":"y","Æ":"Ae","æ":"ae","Þ":"Th","þ":"th","ß":"ss","Ā":"A","Ă":"A","Ą":"A","ā":"a","ă":"a","ą":"a","Ć":"C","Ĉ":"C","Ċ":"C","Č":"C","ć":"c","ĉ":"c","ċ":"c","č":"c","Ď":"D","Đ":"D","ď":"d","đ":"d","Ē":"E","Ĕ":"E","Ė":"E","Ę":"E","Ě":"E","ē":"e","ĕ":"e","ė":"e","ę":"e","ě":"e","Ĝ":"G","Ğ":"G","Ġ":"G","Ģ":"G","ĝ":"g","ğ":"g","ġ":"g","ģ":"g","Ĥ":"H","Ħ":"H","ĥ":"h","ħ":"h","Ĩ":"I","Ī":"I","Ĭ":"I","Į":"I","İ":"I","ĩ":"i","ī":"i","ĭ":"i","į":"i","ı":"i","Ĵ":"J","ĵ":"j","Ķ":"K","ķ":"k","ĸ":"k","Ĺ":"L","Ļ":"L","Ľ":"L","Ŀ":"L","Ł":"L","ĺ":"l","ļ":"l","ľ":"l","ŀ":"l","ł":"l","Ń":"N","Ņ":"N","Ň":"N","Ŋ":"N","ń":"n","ņ":"n","ň":"n","ŋ":"n","Ō":"O","Ŏ":"O","Ő":"O","ō":"o","ŏ":"o","ő":"o","Ŕ":"R","Ŗ":"R","Ř":"R","ŕ":"r","ŗ":"r","ř":"r","Ś":"S","Ŝ":"S","Ş":"S","Š":"S","ś":"s","ŝ":"s","ş":"s","š":"s","Ţ":"T","Ť":"T","Ŧ":"T","ţ":"t","ť":"t","ŧ":"t","Ũ":"U","Ū":"U","Ŭ":"U","Ů":"U","Ű":"U","Ų":"U","ũ":"u","ū":"u","ŭ":"u","ů":"u","ű":"u","ų":"u","Ŵ":"W","ŵ":"w","Ŷ":"Y","ŷ":"y","Ÿ":"Y","Ź":"Z","Ż":"Z","Ž":"Z","ź":"z","ż":"z","ž":"z","IJ":"IJ","ij":"ij","Œ":"Oe","œ":"oe","ʼn":"'n","ſ":"s"}),Xt=Pt({"&":"&","<":"<",">":">",'"':""","'":"'"});function Yt(n){return"\\"+tt[n]}function Qt(n){return Jn.test(n)}function nr(n){var t=-1,r=Array(n.size);return n.forEach((function(n,e){r[++t]=[e,n]})),r}function tr(n,t){return function(r){return n(t(r))}}function rr(n,t){for(var r=-1,e=n.length,u=0,o=[];++r",""":'"',"'":"'"}),fr=function n(t){var r,e=(t=null==t?it:fr.defaults(it.Object(),t,fr.pick(it,Xn))).Array,un=t.Date,wn=t.Error,jn=t.Function,An=t.Math,En=t.Object,Rn=t.RegExp,On=t.String,Sn=t.TypeError,Cn=e.prototype,kn=jn.prototype,Un=En.prototype,Ln=t["__core-js_shared__"],In=kn.toString,Tn=Un.hasOwnProperty,zn=0,Bn=(r=/[^.]+$/.exec(Ln&&Ln.keys&&Ln.keys.IE_PROTO||""))?"Symbol(src)_1."+r:"",Nn=Un.toString,Dn=In.call(En),Pn=it._,Wn=Rn("^"+In.call(Tn).replace(tn,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),qn=ct?t.Buffer:u,Fn=t.Symbol,$n=t.Uint8Array,Mn=qn?qn.allocUnsafe:u,Zn=tr(En.getPrototypeOf,En),Jn=En.create,tt=Un.propertyIsEnumerable,ut=Cn.splice,ot=Fn?Fn.isConcatSpreadable:u,at=Fn?Fn.iterator:u,ft=Fn?Fn.toStringTag:u,st=function(){try{var n=fo(En,"defineProperty");return n({},"",{}),n}catch(n){}}(),lt=t.clearTimeout!==it.clearTimeout&&t.clearTimeout,Ut=un&&un.now!==it.Date.now&&un.now,Pt=t.setTimeout!==it.setTimeout&&t.setTimeout,cr=An.ceil,sr=An.floor,lr=En.getOwnPropertySymbols,pr=qn?qn.isBuffer:u,hr=t.isFinite,dr=Cn.join,vr=tr(En.keys,En),_r=An.max,gr=An.min,yr=un.now,mr=t.parseInt,br=An.random,xr=Cn.reverse,wr=fo(t,"DataView"),jr=fo(t,"Map"),Ar=fo(t,"Promise"),Er=fo(t,"Set"),Rr=fo(t,"WeakMap"),Or=fo(En,"create"),Sr=Rr&&new Rr,Cr={},kr=Bo(wr),Ur=Bo(jr),Lr=Bo(Ar),Ir=Bo(Er),Tr=Bo(Rr),zr=Fn?Fn.prototype:u,Br=zr?zr.valueOf:u,Nr=zr?zr.toString:u;function Dr(n){if(Qi(n)&&!Fi(n)&&!(n instanceof Fr)){if(n instanceof qr)return n;if(Tn.call(n,"__wrapped__"))return No(n)}return new qr(n)}var Pr=function(){function n(){}return function(t){if(!Yi(t))return{};if(Jn)return Jn(t);n.prototype=t;var r=new n;return n.prototype=u,r}}();function Wr(){}function qr(n,t){this.__wrapped__=n,this.__actions__=[],this.__chain__=!!t,this.__index__=0,this.__values__=u}function Fr(n){this.__wrapped__=n,this.__actions__=[],this.__dir__=1,this.__filtered__=!1,this.__iteratees__=[],this.__takeCount__=h,this.__views__=[]}function $r(n){var t=-1,r=null==n?0:n.length;for(this.clear();++t=t?n:t)),n}function ie(n,t,r,e,o,i){var a,f=1&t,c=2&t,s=4&t;if(r&&(a=o?r(n,e,o,i):r(n)),a!==u)return a;if(!Yi(n))return n;var l=Fi(n);if(l){if(a=function(n){var t=n.length,r=new n.constructor(t);return t&&"string"==typeof n[0]&&Tn.call(n,"index")&&(r.index=n.index,r.input=n.input),r}(n),!f)return Ru(n,a)}else{var p=lo(n),h=p==b||p==x;if(Vi(n))return bu(n,f);if(p==A||p==v||h&&!o){if(a=c||h?{}:ho(n),!f)return c?function(n,t){return Ou(n,so(n),t)}(n,function(n,t){return n&&Ou(t,ka(t),n)}(a,n)):function(n,t){return Ou(n,co(n),t)}(n,re(a,n))}else{if(!nt[p])return o?n:{};a=function(n,t,r){var e,u=n.constructor;switch(t){case U:return xu(n);case g:case y:return new u(+n);case L:return function(n,t){var r=t?xu(n.buffer):n.buffer;return new n.constructor(r,n.byteOffset,n.byteLength)}(n,r);case I:case T:case z:case B:case N:case D:case P:case W:case q:return wu(n,r);case w:return new u;case j:case S:return new u(n);case R:return function(n){var t=new n.constructor(n.source,hn.exec(n));return t.lastIndex=n.lastIndex,t}(n);case O:return new u;case C:return e=n,Br?En(Br.call(e)):{}}}(n,p,f)}}i||(i=new Zr);var d=i.get(n);if(d)return d;i.set(n,a),ua(n)?n.forEach((function(e){a.add(ie(e,t,r,e,n,i))})):na(n)&&n.forEach((function(e,u){a.set(u,ie(e,t,r,u,n,i))}));var _=l?u:(s?c?to:no:c?ka:Ca)(n);return bt(_||n,(function(e,u){_&&(e=n[u=e]),Qr(a,u,ie(e,t,r,u,n,i))})),a}function ae(n,t,r){var e=r.length;if(null==n)return!e;for(n=En(n);e--;){var o=r[e],i=t[o],a=n[o];if(a===u&&!(o in n)||!i(a))return!1}return!0}function fe(n,t,r){if("function"!=typeof n)throw new Sn(o);return Co((function(){n.apply(u,r)}),t)}function ce(n,t,r,e){var u=-1,o=At,i=!0,a=n.length,f=[],c=t.length;if(!a)return f;r&&(t=Rt(t,Mt(r))),e?(o=Et,i=!1):t.length>=200&&(o=Vt,i=!1,t=new Vr(t));n:for(;++u-1},Mr.prototype.set=function(n,t){var r=this.__data__,e=ne(r,n);return e<0?(++this.size,r.push([n,t])):r[e][1]=t,this},Hr.prototype.clear=function(){this.size=0,this.__data__={hash:new $r,map:new(jr||Mr),string:new $r}},Hr.prototype.delete=function(n){var t=io(this,n).delete(n);return this.size-=t?1:0,t},Hr.prototype.get=function(n){return io(this,n).get(n)},Hr.prototype.has=function(n){return io(this,n).has(n)},Hr.prototype.set=function(n,t){var r=io(this,n),e=r.size;return r.set(n,t),this.size+=r.size==e?0:1,this},Vr.prototype.add=Vr.prototype.push=function(n){return this.__data__.set(n,i),this},Vr.prototype.has=function(n){return this.__data__.has(n)},Zr.prototype.clear=function(){this.__data__=new Mr,this.size=0},Zr.prototype.delete=function(n){var t=this.__data__,r=t.delete(n);return this.size=t.size,r},Zr.prototype.get=function(n){return this.__data__.get(n)},Zr.prototype.has=function(n){return this.__data__.has(n)},Zr.prototype.set=function(n,t){var r=this.__data__;if(r instanceof Mr){var e=r.__data__;if(!jr||e.length<199)return e.push([n,t]),this.size=++r.size,this;r=this.__data__=new Hr(e)}return r.set(n,t),this.size=r.size,this};var se=ku(ye),le=ku(me,!0);function pe(n,t){var r=!0;return se(n,(function(n,e,u){return r=!!t(n,e,u)})),r}function he(n,t,r){for(var e=-1,o=n.length;++e0&&r(a)?t>1?ve(a,t-1,r,e,u):Ot(u,a):e||(u[u.length]=a)}return u}var _e=Uu(),ge=Uu(!0);function ye(n,t){return n&&_e(n,t,Ca)}function me(n,t){return n&&ge(n,t,Ca)}function be(n,t){return jt(t,(function(t){return Ji(n[t])}))}function xe(n,t){for(var r=0,e=(t=_u(t,n)).length;null!=n&&rt}function Ee(n,t){return null!=n&&Tn.call(n,t)}function Re(n,t){return null!=n&&t in En(n)}function Oe(n,t,r){for(var o=r?Et:At,i=n[0].length,a=n.length,f=a,c=e(a),s=1/0,l=[];f--;){var p=n[f];f&&t&&(p=Rt(p,Mt(t))),s=gr(p.length,s),c[f]=!r&&(t||i>=120&&p.length>=120)?new Vr(f&&p):u}p=n[0];var h=-1,d=c[0];n:for(;++h=a?f:f*("desc"==r[e]?-1:1)}return n.index-t.index}(n,t,r)}))}function Fe(n,t,r){for(var e=-1,u=t.length,o={};++e-1;)a!==n&&ut.call(a,f,1),ut.call(n,f,1);return n}function Me(n,t){for(var r=n?t.length:0,e=r-1;r--;){var u=t[r];if(r==e||u!==o){var o=u;_o(u)?ut.call(n,u,1):fu(n,u)}}return n}function He(n,t){return n+sr(br()*(t-n+1))}function Ve(n,t){var r="";if(!n||t<1||t>l)return r;do{t%2&&(r+=n),(t=sr(t/2))&&(n+=n)}while(t);return r}function Ze(n,t){return ko(Ao(n,t,tf),n+"")}function Ke(n){return Jr(Da(n))}function Je(n,t){var r=Da(n);return Io(r,oe(t,0,r.length))}function Ge(n,t,r,e){if(!Yi(n))return n;for(var o=-1,i=(t=_u(t,n)).length,a=i-1,f=n;null!=f&&++oo?0:o+t),(r=r>o?o:r)<0&&(r+=o),o=t>r?0:r-t>>>0,t>>>=0;for(var i=e(o);++u>>1,i=n[o];null!==i&&!ia(i)&&(r?i<=t:i=200){var c=t?null:Vu(n);if(c)return er(c);i=!1,u=Vt,f=new Vr}else f=t?[]:a;n:for(;++e=e?n:nu(n,t,r)}var mu=lt||function(n){return it.clearTimeout(n)};function bu(n,t){if(t)return n.slice();var r=n.length,e=Mn?Mn(r):new n.constructor(r);return n.copy(e),e}function xu(n){var t=new n.constructor(n.byteLength);return new $n(t).set(new $n(n)),t}function wu(n,t){var r=t?xu(n.buffer):n.buffer;return new n.constructor(r,n.byteOffset,n.length)}function ju(n,t){if(n!==t){var r=n!==u,e=null===n,o=n==n,i=ia(n),a=t!==u,f=null===t,c=t==t,s=ia(t);if(!f&&!s&&!i&&n>t||i&&a&&c&&!f&&!s||e&&a&&c||!r&&c||!o)return 1;if(!e&&!i&&!s&&n1?r[o-1]:u,a=o>2?r[2]:u;for(i=n.length>3&&"function"==typeof i?(o--,i):u,a&&go(r[0],r[1],a)&&(i=o<3?u:i,o=1),t=En(t);++e-1?o[i?t[a]:a]:u}}function Bu(n){return Qu((function(t){var r=t.length,e=r,i=qr.prototype.thru;for(n&&t.reverse();e--;){var a=t[e];if("function"!=typeof a)throw new Sn(o);if(i&&!f&&"wrapper"==eo(a))var f=new qr([],!0)}for(e=f?e:r;++e1&&m.reverse(),h&&lf))return!1;var s=i.get(n),l=i.get(t);if(s&&l)return s==t&&l==n;var p=-1,h=!0,d=2&r?new Vr:u;for(i.set(n,t),i.set(t,n);++p-1&&n%1==0&&n1?"& ":"")+t[e],t=t.join(r>2?", ":" "),n.replace(on,"{\n/* [wrapped with "+t+"] */\n")}(e,function(n,t){return bt(d,(function(r){var e="_."+r[0];t&r[1]&&!At(n,e)&&n.push(e)})),n.sort()}(function(n){var t=n.match(an);return t?t[1].split(fn):[]}(e),r)))}function Lo(n){var t=0,r=0;return function(){var e=yr(),o=16-(e-r);if(r=e,o>0){if(++t>=800)return arguments[0]}else t=0;return n.apply(u,arguments)}}function Io(n,t){var r=-1,e=n.length,o=e-1;for(t=t===u?e:t;++r1?n[t-1]:u;return r="function"==typeof r?(n.pop(),r):u,ei(n,r)}));function si(n){var t=Dr(n);return t.__chain__=!0,t}function li(n,t){return t(n)}var pi=Qu((function(n){var t=n.length,r=t?n[0]:0,e=this.__wrapped__,o=function(t){return ue(t,n)};return!(t>1||this.__actions__.length)&&e instanceof Fr&&_o(r)?((e=e.slice(r,+r+(t?1:0))).__actions__.push({func:li,args:[o],thisArg:u}),new qr(e,this.__chain__).thru((function(n){return t&&!n.length&&n.push(u),n}))):this.thru(o)})),hi=Su((function(n,t,r){Tn.call(n,r)?++n[r]:ee(n,r,1)})),di=zu(qo),vi=zu(Fo);function _i(n,t){return(Fi(n)?bt:se)(n,oo(t,3))}function gi(n,t){return(Fi(n)?xt:le)(n,oo(t,3))}var yi=Su((function(n,t,r){Tn.call(n,r)?n[r].push(t):ee(n,r,[t])})),mi=Ze((function(n,t,r){var u=-1,o="function"==typeof t,i=Mi(n)?e(n.length):[];return se(n,(function(n){i[++u]=o?yt(t,n,r):Se(n,t,r)})),i})),bi=Su((function(n,t,r){ee(n,r,t)}));function xi(n,t){return(Fi(n)?Rt:Be)(n,oo(t,3))}var wi=Su((function(n,t,r){n[r?0:1].push(t)}),(function(){return[[],[]]})),ji=Ze((function(n,t){if(null==n)return[];var r=t.length;return r>1&&go(n,t[0],t[1])?t=[]:r>2&&go(t[0],t[1],t[2])&&(t=[t[0]]),qe(n,ve(t,1),[])})),Ai=Ut||function(){return it.Date.now()};function Ei(n,t,r){return t=r?u:t,t=n&&null==t?n.length:t,Ku(n,c,u,u,u,u,t)}function Ri(n,t){var r;if("function"!=typeof t)throw new Sn(o);return n=pa(n),function(){return--n>0&&(r=t.apply(this,arguments)),n<=1&&(t=u),r}}var Oi=Ze((function(n,t,r){var e=1;if(r.length){var u=rr(r,uo(Oi));e|=f}return Ku(n,e,t,r,u)})),Si=Ze((function(n,t,r){var e=3;if(r.length){var u=rr(r,uo(Si));e|=f}return Ku(t,e,n,r,u)}));function Ci(n,t,r){var e,i,a,f,c,s,l=0,p=!1,h=!1,d=!0;if("function"!=typeof n)throw new Sn(o);function v(t){var r=e,o=i;return e=i=u,l=t,f=n.apply(o,r)}function _(n){return l=n,c=Co(y,t),p?v(n):f}function g(n){var r=n-s;return s===u||r>=t||r<0||h&&n-l>=a}function y(){var n=Ai();if(g(n))return m(n);c=Co(y,function(n){var r=t-(n-s);return h?gr(r,a-(n-l)):r}(n))}function m(n){return c=u,d&&e?v(n):(e=i=u,f)}function b(){var n=Ai(),r=g(n);if(e=arguments,i=this,s=n,r){if(c===u)return _(s);if(h)return mu(c),c=Co(y,t),v(s)}return c===u&&(c=Co(y,t)),f}return t=da(t)||0,Yi(r)&&(p=!!r.leading,a=(h="maxWait"in r)?_r(da(r.maxWait)||0,t):a,d="trailing"in r?!!r.trailing:d),b.cancel=function(){c!==u&&mu(c),l=0,e=s=i=c=u},b.flush=function(){return c===u?f:m(Ai())},b}var ki=Ze((function(n,t){return fe(n,1,t)})),Ui=Ze((function(n,t,r){return fe(n,da(t)||0,r)}));function Li(n,t){if("function"!=typeof n||null!=t&&"function"!=typeof t)throw new Sn(o);var r=function(){var e=arguments,u=t?t.apply(this,e):e[0],o=r.cache;if(o.has(u))return o.get(u);var i=n.apply(this,e);return r.cache=o.set(u,i)||o,i};return r.cache=new(Li.Cache||Hr),r}function Ii(n){if("function"!=typeof n)throw new Sn(o);return function(){var t=arguments;switch(t.length){case 0:return!n.call(this);case 1:return!n.call(this,t[0]);case 2:return!n.call(this,t[0],t[1]);case 3:return!n.call(this,t[0],t[1],t[2])}return!n.apply(this,t)}}Li.Cache=Hr;var Ti=gu((function(n,t){var r=(t=1==t.length&&Fi(t[0])?Rt(t[0],Mt(oo())):Rt(ve(t,1),Mt(oo()))).length;return Ze((function(e){for(var u=-1,o=gr(e.length,r);++u=t})),qi=Ce(function(){return arguments}())?Ce:function(n){return Qi(n)&&Tn.call(n,"callee")&&!tt.call(n,"callee")},Fi=e.isArray,$i=pt?Mt(pt):function(n){return Qi(n)&&je(n)==U};function Mi(n){return null!=n&&Xi(n.length)&&!Ji(n)}function Hi(n){return Qi(n)&&Mi(n)}var Vi=pr||vf,Zi=ht?Mt(ht):function(n){return Qi(n)&&je(n)==y};function Ki(n){if(!Qi(n))return!1;var t=je(n);return t==m||"[object DOMException]"==t||"string"==typeof n.message&&"string"==typeof n.name&&!ra(n)}function Ji(n){if(!Yi(n))return!1;var t=je(n);return t==b||t==x||"[object AsyncFunction]"==t||"[object Proxy]"==t}function Gi(n){return"number"==typeof n&&n==pa(n)}function Xi(n){return"number"==typeof n&&n>-1&&n%1==0&&n<=l}function Yi(n){var t=typeof n;return null!=n&&("object"==t||"function"==t)}function Qi(n){return null!=n&&"object"==typeof n}var na=dt?Mt(dt):function(n){return Qi(n)&&lo(n)==w};function ta(n){return"number"==typeof n||Qi(n)&&je(n)==j}function ra(n){if(!Qi(n)||je(n)!=A)return!1;var t=Zn(n);if(null===t)return!0;var r=Tn.call(t,"constructor")&&t.constructor;return"function"==typeof r&&r instanceof r&&In.call(r)==Dn}var ea=vt?Mt(vt):function(n){return Qi(n)&&je(n)==R},ua=_t?Mt(_t):function(n){return Qi(n)&&lo(n)==O};function oa(n){return"string"==typeof n||!Fi(n)&&Qi(n)&&je(n)==S}function ia(n){return"symbol"==typeof n||Qi(n)&&je(n)==C}var aa=gt?Mt(gt):function(n){return Qi(n)&&Xi(n.length)&&!!Qn[je(n)]},fa=$u(ze),ca=$u((function(n,t){return n<=t}));function sa(n){if(!n)return[];if(Mi(n))return oa(n)?or(n):Ru(n);if(at&&n[at])return function(n){for(var t,r=[];!(t=n.next()).done;)r.push(t.value);return r}(n[at]());var t=lo(n);return(t==w?nr:t==O?er:Da)(n)}function la(n){return n?(n=da(n))===s||n===-1/0?17976931348623157e292*(n<0?-1:1):n==n?n:0:0===n?n:0}function pa(n){var t=la(n),r=t%1;return t==t?r?t-r:t:0}function ha(n){return n?oe(pa(n),0,h):0}function da(n){if("number"==typeof n)return n;if(ia(n))return p;if(Yi(n)){var t="function"==typeof n.valueOf?n.valueOf():n;n=Yi(t)?t+"":t}if("string"!=typeof n)return 0===n?n:+n;n=$t(n);var r=vn.test(n);return r||gn.test(n)?et(n.slice(2),r?2:8):dn.test(n)?p:+n}function va(n){return Ou(n,ka(n))}function _a(n){return null==n?"":iu(n)}var ga=Cu((function(n,t){if(xo(t)||Mi(t))Ou(t,Ca(t),n);else for(var r in t)Tn.call(t,r)&&Qr(n,r,t[r])})),ya=Cu((function(n,t){Ou(t,ka(t),n)})),ma=Cu((function(n,t,r,e){Ou(t,ka(t),n,e)})),ba=Cu((function(n,t,r,e){Ou(t,Ca(t),n,e)})),xa=Qu(ue),wa=Ze((function(n,t){n=En(n);var r=-1,e=t.length,o=e>2?t[2]:u;for(o&&go(t[0],t[1],o)&&(e=1);++r1),t})),Ou(n,to(n),r),e&&(r=ie(r,7,Xu));for(var u=t.length;u--;)fu(r,t[u]);return r})),Ta=Qu((function(n,t){return null==n?{}:function(n,t){return Fe(n,t,(function(t,r){return Ea(n,r)}))}(n,t)}));function za(n,t){if(null==n)return{};var r=Rt(to(n),(function(n){return[n]}));return t=oo(t),Fe(n,r,(function(n,r){return t(n,r[0])}))}var Ba=Zu(Ca),Na=Zu(ka);function Da(n){return null==n?[]:Ht(n,Ca(n))}var Pa=Iu((function(n,t,r){return t=t.toLowerCase(),n+(r?Wa(t):t)}));function Wa(n){return Ka(_a(n).toLowerCase())}function qa(n){return(n=_a(n))&&n.replace(mn,Gt).replace(Vn,"")}var Fa=Iu((function(n,t,r){return n+(r?"-":"")+t.toLowerCase()})),$a=Iu((function(n,t,r){return n+(r?" ":"")+t.toLowerCase()})),Ma=Lu("toLowerCase"),Ha=Iu((function(n,t,r){return n+(r?"_":"")+t.toLowerCase()})),Va=Iu((function(n,t,r){return n+(r?" ":"")+Ka(t)})),Za=Iu((function(n,t,r){return n+(r?" ":"")+t.toUpperCase()})),Ka=Lu("toUpperCase");function Ja(n,t,r){return n=_a(n),(t=r?u:t)===u?function(n){return Gn.test(n)}(n)?function(n){return n.match(Kn)||[]}(n):function(n){return n.match(cn)||[]}(n):n.match(t)||[]}var Ga=Ze((function(n,t){try{return yt(n,u,t)}catch(n){return Ki(n)?n:new wn(n)}})),Xa=Qu((function(n,t){return bt(t,(function(t){t=zo(t),ee(n,t,Oi(n[t],n))})),n}));function Ya(n){return function(){return n}}var Qa=Bu(),nf=Bu(!0);function tf(n){return n}function rf(n){return Ie("function"==typeof n?n:ie(n,1))}var ef=Ze((function(n,t){return function(r){return Se(r,n,t)}})),uf=Ze((function(n,t){return function(r){return Se(n,r,t)}}));function of(n,t,r){var e=Ca(t),u=be(t,e);null!=r||Yi(t)&&(u.length||!e.length)||(r=t,t=n,n=this,u=be(t,Ca(t)));var o=!(Yi(r)&&"chain"in r&&!r.chain),i=Ji(n);return bt(u,(function(r){var e=t[r];n[r]=e,i&&(n.prototype[r]=function(){var t=this.__chain__;if(o||t){var r=n(this.__wrapped__),u=r.__actions__=Ru(this.__actions__);return u.push({func:e,args:arguments,thisArg:n}),r.__chain__=t,r}return e.apply(n,Ot([this.value()],arguments))})})),n}function af(){}var ff=Wu(Rt),cf=Wu(wt),sf=Wu(kt);function lf(n){return yo(n)?Dt(zo(n)):function(n){return function(t){return xe(t,n)}}(n)}var pf=Fu(),hf=Fu(!0);function df(){return[]}function vf(){return!1}var _f,gf=Pu((function(n,t){return n+t}),0),yf=Hu("ceil"),mf=Pu((function(n,t){return n/t}),1),bf=Hu("floor"),xf=Pu((function(n,t){return n*t}),1),wf=Hu("round"),jf=Pu((function(n,t){return n-t}),0);return Dr.after=function(n,t){if("function"!=typeof t)throw new Sn(o);return n=pa(n),function(){if(--n<1)return t.apply(this,arguments)}},Dr.ary=Ei,Dr.assign=ga,Dr.assignIn=ya,Dr.assignInWith=ma,Dr.assignWith=ba,Dr.at=xa,Dr.before=Ri,Dr.bind=Oi,Dr.bindAll=Xa,Dr.bindKey=Si,Dr.castArray=function(){if(!arguments.length)return[];var n=arguments[0];return Fi(n)?n:[n]},Dr.chain=si,Dr.chunk=function(n,t,r){t=(r?go(n,t,r):t===u)?1:_r(pa(t),0);var o=null==n?0:n.length;if(!o||t<1)return[];for(var i=0,a=0,f=e(cr(o/t));io?0:o+r),(e=e===u||e>o?o:pa(e))<0&&(e+=o),e=r>e?0:ha(e);r>>0)?(n=_a(n))&&("string"==typeof t||null!=t&&!ea(t))&&!(t=iu(t))&&Qt(n)?yu(or(n),0,r):n.split(t,r):[]},Dr.spread=function(n,t){if("function"!=typeof n)throw new Sn(o);return t=null==t?0:_r(pa(t),0),Ze((function(r){var e=r[t],u=yu(r,0,t);return e&&Ot(u,e),yt(n,this,u)}))},Dr.tail=function(n){var t=null==n?0:n.length;return t?nu(n,1,t):[]},Dr.take=function(n,t,r){return n&&n.length?nu(n,0,(t=r||t===u?1:pa(t))<0?0:t):[]},Dr.takeRight=function(n,t,r){var e=null==n?0:n.length;return e?nu(n,(t=e-(t=r||t===u?1:pa(t)))<0?0:t,e):[]},Dr.takeRightWhile=function(n,t){return n&&n.length?su(n,oo(t,3),!1,!0):[]},Dr.takeWhile=function(n,t){return n&&n.length?su(n,oo(t,3)):[]},Dr.tap=function(n,t){return t(n),n},Dr.throttle=function(n,t,r){var e=!0,u=!0;if("function"!=typeof n)throw new Sn(o);return Yi(r)&&(e="leading"in r?!!r.leading:e,u="trailing"in r?!!r.trailing:u),Ci(n,t,{leading:e,maxWait:t,trailing:u})},Dr.thru=li,Dr.toArray=sa,Dr.toPairs=Ba,Dr.toPairsIn=Na,Dr.toPath=function(n){return Fi(n)?Rt(n,zo):ia(n)?[n]:Ru(To(_a(n)))},Dr.toPlainObject=va,Dr.transform=function(n,t,r){var e=Fi(n),u=e||Vi(n)||aa(n);if(t=oo(t,4),null==r){var o=n&&n.constructor;r=u?e?new o:[]:Yi(n)&&Ji(o)?Pr(Zn(n)):{}}return(u?bt:ye)(n,(function(n,e,u){return t(r,n,e,u)})),r},Dr.unary=function(n){return Ei(n,1)},Dr.union=Qo,Dr.unionBy=ni,Dr.unionWith=ti,Dr.uniq=function(n){return n&&n.length?au(n):[]},Dr.uniqBy=function(n,t){return n&&n.length?au(n,oo(t,2)):[]},Dr.uniqWith=function(n,t){return t="function"==typeof t?t:u,n&&n.length?au(n,u,t):[]},Dr.unset=function(n,t){return null==n||fu(n,t)},Dr.unzip=ri,Dr.unzipWith=ei,Dr.update=function(n,t,r){return null==n?n:cu(n,t,vu(r))},Dr.updateWith=function(n,t,r,e){return e="function"==typeof e?e:u,null==n?n:cu(n,t,vu(r),e)},Dr.values=Da,Dr.valuesIn=function(n){return null==n?[]:Ht(n,ka(n))},Dr.without=ui,Dr.words=Ja,Dr.wrap=function(n,t){return zi(vu(t),n)},Dr.xor=oi,Dr.xorBy=ii,Dr.xorWith=ai,Dr.zip=fi,Dr.zipObject=function(n,t){return hu(n||[],t||[],Qr)},Dr.zipObjectDeep=function(n,t){return hu(n||[],t||[],Ge)},Dr.zipWith=ci,Dr.entries=Ba,Dr.entriesIn=Na,Dr.extend=ya,Dr.extendWith=ma,of(Dr,Dr),Dr.add=gf,Dr.attempt=Ga,Dr.camelCase=Pa,Dr.capitalize=Wa,Dr.ceil=yf,Dr.clamp=function(n,t,r){return r===u&&(r=t,t=u),r!==u&&(r=(r=da(r))==r?r:0),t!==u&&(t=(t=da(t))==t?t:0),oe(da(n),t,r)},Dr.clone=function(n){return ie(n,4)},Dr.cloneDeep=function(n){return ie(n,5)},Dr.cloneDeepWith=function(n,t){return ie(n,5,t="function"==typeof t?t:u)},Dr.cloneWith=function(n,t){return ie(n,4,t="function"==typeof t?t:u)},Dr.conformsTo=function(n,t){return null==t||ae(n,t,Ca(t))},Dr.deburr=qa,Dr.defaultTo=function(n,t){return null==n||n!=n?t:n},Dr.divide=mf,Dr.endsWith=function(n,t,r){n=_a(n),t=iu(t);var e=n.length,o=r=r===u?e:oe(pa(r),0,e);return(r-=t.length)>=0&&n.slice(r,o)==t},Dr.eq=Di,Dr.escape=function(n){return(n=_a(n))&&K.test(n)?n.replace(V,Xt):n},Dr.escapeRegExp=function(n){return(n=_a(n))&&rn.test(n)?n.replace(tn,"\\$&"):n},Dr.every=function(n,t,r){var e=Fi(n)?wt:pe;return r&&go(n,t,r)&&(t=u),e(n,oo(t,3))},Dr.find=di,Dr.findIndex=qo,Dr.findKey=function(n,t){return Lt(n,oo(t,3),ye)},Dr.findLast=vi,Dr.findLastIndex=Fo,Dr.findLastKey=function(n,t){return Lt(n,oo(t,3),me)},Dr.floor=bf,Dr.forEach=_i,Dr.forEachRight=gi,Dr.forIn=function(n,t){return null==n?n:_e(n,oo(t,3),ka)},Dr.forInRight=function(n,t){return null==n?n:ge(n,oo(t,3),ka)},Dr.forOwn=function(n,t){return n&&ye(n,oo(t,3))},Dr.forOwnRight=function(n,t){return n&&me(n,oo(t,3))},Dr.get=Aa,Dr.gt=Pi,Dr.gte=Wi,Dr.has=function(n,t){return null!=n&&po(n,t,Ee)},Dr.hasIn=Ea,Dr.head=Mo,Dr.identity=tf,Dr.includes=function(n,t,r,e){n=Mi(n)?n:Da(n),r=r&&!e?pa(r):0;var u=n.length;return r<0&&(r=_r(u+r,0)),oa(n)?r<=u&&n.indexOf(t,r)>-1:!!u&&Tt(n,t,r)>-1},Dr.indexOf=function(n,t,r){var e=null==n?0:n.length;if(!e)return-1;var u=null==r?0:pa(r);return u<0&&(u=_r(e+u,0)),Tt(n,t,u)},Dr.inRange=function(n,t,r){return t=la(t),r===u?(r=t,t=0):r=la(r),function(n,t,r){return n>=gr(t,r)&&n<_r(t,r)}(n=da(n),t,r)},Dr.invoke=Sa,Dr.isArguments=qi,Dr.isArray=Fi,Dr.isArrayBuffer=$i,Dr.isArrayLike=Mi,Dr.isArrayLikeObject=Hi,Dr.isBoolean=function(n){return!0===n||!1===n||Qi(n)&&je(n)==g},Dr.isBuffer=Vi,Dr.isDate=Zi,Dr.isElement=function(n){return Qi(n)&&1===n.nodeType&&!ra(n)},Dr.isEmpty=function(n){if(null==n)return!0;if(Mi(n)&&(Fi(n)||"string"==typeof n||"function"==typeof n.splice||Vi(n)||aa(n)||qi(n)))return!n.length;var t=lo(n);if(t==w||t==O)return!n.size;if(xo(n))return!Te(n).length;for(var r in n)if(Tn.call(n,r))return!1;return!0},Dr.isEqual=function(n,t){return ke(n,t)},Dr.isEqualWith=function(n,t,r){var e=(r="function"==typeof r?r:u)?r(n,t):u;return e===u?ke(n,t,u,r):!!e},Dr.isError=Ki,Dr.isFinite=function(n){return"number"==typeof n&&hr(n)},Dr.isFunction=Ji,Dr.isInteger=Gi,Dr.isLength=Xi,Dr.isMap=na,Dr.isMatch=function(n,t){return n===t||Ue(n,t,ao(t))},Dr.isMatchWith=function(n,t,r){return r="function"==typeof r?r:u,Ue(n,t,ao(t),r)},Dr.isNaN=function(n){return ta(n)&&n!=+n},Dr.isNative=function(n){if(bo(n))throw new wn("Unsupported core-js use. Try https://npms.io/search?q=ponyfill.");return Le(n)},Dr.isNil=function(n){return null==n},Dr.isNull=function(n){return null===n},Dr.isNumber=ta,Dr.isObject=Yi,Dr.isObjectLike=Qi,Dr.isPlainObject=ra,Dr.isRegExp=ea,Dr.isSafeInteger=function(n){return Gi(n)&&n>=-9007199254740991&&n<=l},Dr.isSet=ua,Dr.isString=oa,Dr.isSymbol=ia,Dr.isTypedArray=aa,Dr.isUndefined=function(n){return n===u},Dr.isWeakMap=function(n){return Qi(n)&&lo(n)==k},Dr.isWeakSet=function(n){return Qi(n)&&"[object WeakSet]"==je(n)},Dr.join=function(n,t){return null==n?"":dr.call(n,t)},Dr.kebabCase=Fa,Dr.last=Ko,Dr.lastIndexOf=function(n,t,r){var e=null==n?0:n.length;if(!e)return-1;var o=e;return r!==u&&(o=(o=pa(r))<0?_r(e+o,0):gr(o,e-1)),t==t?function(n,t,r){for(var e=r+1;e--;)if(n[e]===t)return e;return e}(n,t,o):It(n,Bt,o,!0)},Dr.lowerCase=$a,Dr.lowerFirst=Ma,Dr.lt=fa,Dr.lte=ca,Dr.max=function(n){return n&&n.length?he(n,tf,Ae):u},Dr.maxBy=function(n,t){return n&&n.length?he(n,oo(t,2),Ae):u},Dr.mean=function(n){return Nt(n,tf)},Dr.meanBy=function(n,t){return Nt(n,oo(t,2))},Dr.min=function(n){return n&&n.length?he(n,tf,ze):u},Dr.minBy=function(n,t){return n&&n.length?he(n,oo(t,2),ze):u},Dr.stubArray=df,Dr.stubFalse=vf,Dr.stubObject=function(){return{}},Dr.stubString=function(){return""},Dr.stubTrue=function(){return!0},Dr.multiply=xf,Dr.nth=function(n,t){return n&&n.length?We(n,pa(t)):u},Dr.noConflict=function(){return it._===this&&(it._=Pn),this},Dr.noop=af,Dr.now=Ai,Dr.pad=function(n,t,r){n=_a(n);var e=(t=pa(t))?ur(n):0;if(!t||e>=t)return n;var u=(t-e)/2;return qu(sr(u),r)+n+qu(cr(u),r)},Dr.padEnd=function(n,t,r){n=_a(n);var e=(t=pa(t))?ur(n):0;return t&&et){var e=n;n=t,t=e}if(r||n%1||t%1){var o=br();return gr(n+o*(t-n+rt("1e-"+((o+"").length-1))),t)}return He(n,t)},Dr.reduce=function(n,t,r){var e=Fi(n)?St:Wt,u=arguments.length<3;return e(n,oo(t,4),r,u,se)},Dr.reduceRight=function(n,t,r){var e=Fi(n)?Ct:Wt,u=arguments.length<3;return e(n,oo(t,4),r,u,le)},Dr.repeat=function(n,t,r){return t=(r?go(n,t,r):t===u)?1:pa(t),Ve(_a(n),t)},Dr.replace=function(){var n=arguments,t=_a(n[0]);return n.length<3?t:t.replace(n[1],n[2])},Dr.result=function(n,t,r){var e=-1,o=(t=_u(t,n)).length;for(o||(o=1,n=u);++el)return[];var r=h,e=gr(n,h);t=oo(t),n-=h;for(var u=Ft(e,t);++r=i)return n;var f=r-ur(e);if(f<1)return e;var c=a?yu(a,0,f).join(""):n.slice(0,f);if(o===u)return c+e;if(a&&(f+=c.length-f),ea(o)){if(n.slice(f).search(o)){var s,l=c;for(o.global||(o=Rn(o.source,_a(hn.exec(o))+"g")),o.lastIndex=0;s=o.exec(l);)var p=s.index;c=c.slice(0,p===u?f:p)}}else if(n.indexOf(iu(o),f)!=f){var h=c.lastIndexOf(o);h>-1&&(c=c.slice(0,h))}return c+e},Dr.unescape=function(n){return(n=_a(n))&&Z.test(n)?n.replace(H,ar):n},Dr.uniqueId=function(n){var t=++zn;return _a(n)+t},Dr.upperCase=Za,Dr.upperFirst=Ka,Dr.each=_i,Dr.eachRight=gi,Dr.first=Mo,of(Dr,(_f={},ye(Dr,(function(n,t){Tn.call(Dr.prototype,t)||(_f[t]=n)})),_f),{chain:!1}),Dr.VERSION="4.17.21",bt(["bind","bindKey","curry","curryRight","partial","partialRight"],(function(n){Dr[n].placeholder=Dr})),bt(["drop","take"],(function(n,t){Fr.prototype[n]=function(r){r=r===u?1:_r(pa(r),0);var e=this.__filtered__&&!t?new Fr(this):this.clone();return e.__filtered__?e.__takeCount__=gr(r,e.__takeCount__):e.__views__.push({size:gr(r,h),type:n+(e.__dir__<0?"Right":"")}),e},Fr.prototype[n+"Right"]=function(t){return this.reverse()[n](t).reverse()}})),bt(["filter","map","takeWhile"],(function(n,t){var r=t+1,e=1==r||3==r;Fr.prototype[n]=function(n){var t=this.clone();return t.__iteratees__.push({iteratee:oo(n,3),type:r}),t.__filtered__=t.__filtered__||e,t}})),bt(["head","last"],(function(n,t){var r="take"+(t?"Right":"");Fr.prototype[n]=function(){return this[r](1).value()[0]}})),bt(["initial","tail"],(function(n,t){var r="drop"+(t?"":"Right");Fr.prototype[n]=function(){return this.__filtered__?new Fr(this):this[r](1)}})),Fr.prototype.compact=function(){return this.filter(tf)},Fr.prototype.find=function(n){return this.filter(n).head()},Fr.prototype.findLast=function(n){return this.reverse().find(n)},Fr.prototype.invokeMap=Ze((function(n,t){return"function"==typeof n?new Fr(this):this.map((function(r){return Se(r,n,t)}))})),Fr.prototype.reject=function(n){return this.filter(Ii(oo(n)))},Fr.prototype.slice=function(n,t){n=pa(n);var r=this;return r.__filtered__&&(n>0||t<0)?new Fr(r):(n<0?r=r.takeRight(-n):n&&(r=r.drop(n)),t!==u&&(r=(t=pa(t))<0?r.dropRight(-t):r.take(t-n)),r)},Fr.prototype.takeRightWhile=function(n){return this.reverse().takeWhile(n).reverse()},Fr.prototype.toArray=function(){return this.take(h)},ye(Fr.prototype,(function(n,t){var r=/^(?:filter|find|map|reject)|While$/.test(t),e=/^(?:head|last)$/.test(t),o=Dr[e?"take"+("last"==t?"Right":""):t],i=e||/^find/.test(t);o&&(Dr.prototype[t]=function(){var t=this.__wrapped__,a=e?[1]:arguments,f=t instanceof Fr,c=a[0],s=f||Fi(t),l=function(n){var t=o.apply(Dr,Ot([n],a));return e&&p?t[0]:t};s&&r&&"function"==typeof c&&1!=c.length&&(f=s=!1);var p=this.__chain__,h=!!this.__actions__.length,d=i&&!p,v=f&&!h;if(!i&&s){t=v?t:new Fr(this);var _=n.apply(t,a);return _.__actions__.push({func:li,args:[l],thisArg:u}),new qr(_,p)}return d&&v?n.apply(this,a):(_=this.thru(l),d?e?_.value()[0]:_.value():_)})})),bt(["pop","push","shift","sort","splice","unshift"],(function(n){var t=Cn[n],r=/^(?:push|sort|unshift)$/.test(n)?"tap":"thru",e=/^(?:pop|shift)$/.test(n);Dr.prototype[n]=function(){var n=arguments;if(e&&!this.__chain__){var u=this.value();return t.apply(Fi(u)?u:[],n)}return this[r]((function(r){return t.apply(Fi(r)?r:[],n)}))}})),ye(Fr.prototype,(function(n,t){var r=Dr[t];if(r){var e=r.name+"";Tn.call(Cr,e)||(Cr[e]=[]),Cr[e].push({name:t,func:r})}})),Cr[Nu(u,2).name]=[{name:"wrapper",func:u}],Fr.prototype.clone=function(){var n=new Fr(this.__wrapped__);return n.__actions__=Ru(this.__actions__),n.__dir__=this.__dir__,n.__filtered__=this.__filtered__,n.__iteratees__=Ru(this.__iteratees__),n.__takeCount__=this.__takeCount__,n.__views__=Ru(this.__views__),n},Fr.prototype.reverse=function(){if(this.__filtered__){var n=new Fr(this);n.__dir__=-1,n.__filtered__=!0}else(n=this.clone()).__dir__*=-1;return n},Fr.prototype.value=function(){var n=this.__wrapped__.value(),t=this.__dir__,r=Fi(n),e=t<0,u=r?n.length:0,o=function(n,t,r){for(var e=-1,u=r.length;++e=this.__values__.length;return{done:n,value:n?u:this.__values__[this.__index__++]}},Dr.prototype.plant=function(n){for(var t,r=this;r instanceof Wr;){var e=No(r);e.__index__=0,e.__values__=u,t?o.__wrapped__=e:t=e;var o=e;r=r.__wrapped__}return o.__wrapped__=n,t},Dr.prototype.reverse=function(){var n=this.__wrapped__;if(n instanceof Fr){var t=n;return this.__actions__.length&&(t=new Fr(this)),(t=t.reverse()).__actions__.push({func:li,args:[Yo],thisArg:u}),new qr(t,this.__chain__)}return this.thru(Yo)},Dr.prototype.toJSON=Dr.prototype.valueOf=Dr.prototype.value=function(){return lu(this.__wrapped__,this.__actions__)},Dr.prototype.first=Dr.prototype.head,at&&(Dr.prototype[at]=function(){return this}),Dr}();it._=fr,(e=function(){return fr}.call(t,r,t,n))===u||(n.exports=e)}.call(this)},"?5ebd":function(n,t,r){n.exports=r}},t={};function r(e){var u=t[e];if(void 0!==u)return u.exports;var o=t[e]={id:e,loaded:!1,exports:{}};return n[e].call(o.exports,o,o.exports,r),o.loaded=!0,o.exports}r.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(n){if("object"==typeof window)return window}}(),r.nmd=function(n){return n.paths=[],n.children||(n.children=[]),n};var e=r("?5ebd");dll_tool=e}();
--------------------------------------------------------------------------------
/build/static/dll/dll_tool_441c03.production.js.VERSION.txt:
--------------------------------------------------------------------------------
1 | {
2 | "lodash": "^4.17.21",
3 | "axios": "^0.21.1"
4 | }
--------------------------------------------------------------------------------
/build/static/js/main.f961ed.js.LICENSE.txt:
--------------------------------------------------------------------------------
1 | /*!
2 | Copyright (c) 2018 Jed Watson.
3 | Licensed under the MIT License (MIT), see
4 | http://jedwatson.github.io/classnames
5 | */
6 |
7 | /** @license React v16.13.1
8 | * react-is.production.min.js
9 | *
10 | * Copyright (c) Facebook, Inc. and its affiliates.
11 | *
12 | * This source code is licensed under the MIT license found in the
13 | * LICENSE file in the root directory of this source tree.
14 | */
15 |
--------------------------------------------------------------------------------
/dll/basic_manifest_development.json:
--------------------------------------------------------------------------------
1 | {"name":"dll_basic","content":{"./node_modules/react-dom/index.js":{"id":"./node_modules/react-dom/index.js","buildMeta":{"exportsType":"dynamic","defaultObject":"redirect"},"exports":["__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED","createPortal","findDOMNode","flushSync","hydrate","render","unmountComponentAtNode","unstable_batchedUpdates","unstable_createPortal","unstable_renderSubtreeIntoContainer","version"]},"./node_modules/react/index.js":{"id":"./node_modules/react/index.js","buildMeta":{"exportsType":"dynamic","defaultObject":"redirect"},"exports":["Children","Component","Fragment","Profiler","PureComponent","StrictMode","Suspense","__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED","cloneElement","createContext","createElement","createFactory","createRef","forwardRef","isValidElement","lazy","memo","useCallback","useContext","useDebugValue","useEffect","useImperativeHandle","useLayoutEffect","useMemo","useReducer","useRef","useState","version"]}}}
--------------------------------------------------------------------------------
/dll/basic_manifest_production.json:
--------------------------------------------------------------------------------
1 | {"name":"dll_basic","content":{"./node_modules/react-dom/index.js":{"id":"./node_modules/react-dom/index.js","buildMeta":{"exportsType":"dynamic","defaultObject":"redirect"},"exports":["__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED","createPortal","findDOMNode","flushSync","hydrate","render","unmountComponentAtNode","unstable_batchedUpdates","unstable_createPortal","unstable_renderSubtreeIntoContainer","version"]},"./node_modules/react/index.js":{"id":"./node_modules/react/index.js","buildMeta":{"exportsType":"dynamic","defaultObject":"redirect"},"exports":["Children","Component","Fragment","Profiler","PureComponent","StrictMode","Suspense","__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED","cloneElement","createContext","createElement","createFactory","createRef","forwardRef","isValidElement","lazy","memo","useCallback","useContext","useDebugValue","useEffect","useImperativeHandle","useLayoutEffect","useMemo","useReducer","useRef","useState","version"]}}}
--------------------------------------------------------------------------------
/dll/dll_basic_cfedf4.production.js.VERSION.txt:
--------------------------------------------------------------------------------
1 | {
2 | "react": "^17.0.2",
3 | "react-dom": "^17.0.2"
4 | }
--------------------------------------------------------------------------------
/dll/dll_tool_441c03.production.js.VERSION.txt:
--------------------------------------------------------------------------------
1 | {
2 | "lodash": "^4.17.21",
3 | "axios": "^0.21.1"
4 | }
--------------------------------------------------------------------------------
/dll/tool_manifest_development.json:
--------------------------------------------------------------------------------
1 | {"name":"dll_tool","content":{"./node_modules/axios/index.js":{"id":"./node_modules/axios/index.js","buildMeta":{"exportsType":"dynamic","defaultObject":"redirect"}},"./node_modules/lodash/lodash.js":{"id":"./node_modules/lodash/lodash.js","buildMeta":{}}}}
--------------------------------------------------------------------------------
/dll/tool_manifest_production.json:
--------------------------------------------------------------------------------
1 | {"name":"dll_tool","content":{"./node_modules/axios/index.js":{"id":"./node_modules/axios/index.js","buildMeta":{"exportsType":"dynamic","defaultObject":"redirect"}},"./node_modules/lodash/lodash.js":{"id":"./node_modules/lodash/lodash.js","buildMeta":{}}}}
--------------------------------------------------------------------------------
/lint-staged.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | 'package.json': ['npm run check:dll'],
3 | 'src/**/*.{css,md,html}': ['prettier --write'],
4 | 'src/**/*.less': (fileNames) => {
5 | const fileStr = fileNames.join(' ');
6 | return [
7 | fileNames.length > 30 ? 'npm run lint-staged:style --fix src/' : `npm run lint-staged:style ${fileStr}`,
8 | `prettier --write ${fileStr}`,
9 | ];
10 | },
11 | 'src/**/*.{js,jsx}': (fileNames) => {
12 | const fileStr = fileNames.join(' ');
13 | return [
14 | `prettier --write ${fileStr}`,
15 | fileNames.length > 30 ? 'npm run lint-staged:js src/' : `npm run lint-staged:js ${fileStr}`
16 | ];
17 | },
18 | 'src/**/*.{ts,tsx}': (fileNames) => {
19 | return fileNames.length > 30
20 | ? 'npm run lint-staged:ts src/'
21 | : `npm run lint-staged:ts ${fileNames.join(' ')}`;
22 | },
23 | '**/*.{ts,tsx}': () => 'npm run check:tsc',
24 | };
25 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react16-router4-template",
3 | "version": "1.0.0",
4 | "main": "index.js",
5 | "author": "mjzhang1993 ",
6 | "license": "MIT",
7 | "scripts": {
8 | "start": "node scripts/start.js",
9 | "build": "stylelint --syntax scss src/ && node scripts/build.js",
10 | "build:dll": "node scripts/dll.js",
11 | "lint-staged": "lint-staged",
12 | "lint-staged:js": "cross-env ESLINT_ENV=commit eslint --fix --ext .js,.jsx",
13 | "lint-staged:ts": "cross-env ESLINT_ENV=commit eslint --fix --ext .ts,.tsx",
14 | "lint-staged:style": "stylelint --fix --syntax scss",
15 | "check:tsc": "tsc -p ./tsconfig.prod.json",
16 | "check:dll": "node scripts/dll-version-check.js",
17 | "eslintFix": "eslint --fix src/**/*.tsx --fix src/**/*.ts",
18 | "prepare": "husky install"
19 | },
20 | "homepage": ".",
21 | "dependencies": {
22 | "@babel/runtime": "^7.14.6",
23 | "@reduxjs/toolkit": "^1.6.0",
24 | "antd": "^4.16.6",
25 | "axios": "^0.21.1",
26 | "core-js-bundle": "^3.15.1",
27 | "hoist-non-react-statics": "^3.3.2",
28 | "immer": "^9.0.3",
29 | "lodash": "^4.17.21",
30 | "qs": "^6.10.1",
31 | "react": "^17.0.2",
32 | "react-dom": "^17.0.2",
33 | "react-redux": "^7.2.4",
34 | "react-router-dom": "^5.2.0",
35 | "redux": "^4.1.0"
36 | },
37 | "devDependencies": {
38 | "@babel/core": "^7.14.6",
39 | "@babel/plugin-proposal-class-properties": "^7.14.5",
40 | "@babel/plugin-proposal-decorators": "^7.14.5",
41 | "@babel/plugin-proposal-export-default-from": "^7.14.5",
42 | "@babel/plugin-proposal-export-namespace-from": "^7.14.5",
43 | "@babel/plugin-proposal-function-sent": "^7.14.5",
44 | "@babel/plugin-syntax-dynamic-import": "^7.8.3",
45 | "@babel/plugin-transform-classes": "^7.14.5",
46 | "@babel/plugin-transform-runtime": "^7.14.5",
47 | "@babel/preset-env": "^7.14.7",
48 | "@babel/preset-react": "^7.14.5",
49 | "@babel/preset-typescript": "^7.14.5",
50 | "@types/hoist-non-react-statics": "^3.3.1",
51 | "@types/lodash": "^4.14.170",
52 | "@types/qs": "^6.9.6",
53 | "@types/react": "^17.0.11",
54 | "@types/react-dom": "^17.0.8",
55 | "@types/react-router-dom": "^5.1.7",
56 | "@types/validator": "^13.1.4",
57 | "@typescript-eslint/eslint-plugin": "^4.28.1",
58 | "@typescript-eslint/parser": "^4.28.1",
59 | "autoprefixer": "^10.2.6",
60 | "babel-loader": "^8.2.2",
61 | "babel-plugin-import": "^1.13.3",
62 | "chalk": "^4.1.1",
63 | "copy-webpack-plugin": "^9.0.1",
64 | "cross-env": "^7.0.3",
65 | "css-loader": "^5.2.6",
66 | "css-minimizer-webpack-plugin": "^3.0.2",
67 | "eslint": "^7.29.0",
68 | "eslint-config-airbnb-typescript": "^12.3.1",
69 | "eslint-config-prettier": "^8.3.0",
70 | "eslint-plugin-import": "^2.23.4",
71 | "eslint-plugin-jsx-a11y": "^6.4.1",
72 | "eslint-plugin-prettier": "^3.4.0",
73 | "eslint-plugin-react": "^7.24.0",
74 | "eslint-plugin-react-hooks": "^4.2.0",
75 | "eslint-webpack-plugin": "^2.5.4",
76 | "html-webpack-plugin": "^5.3.2",
77 | "html-webpack-tags-plugin": "^3.0.1",
78 | "husky": "^6.0.0",
79 | "lint-staged": "^11.0.0",
80 | "mini-css-extract-plugin": "^1.6.2",
81 | "postcss": "^8.3.5",
82 | "postcss-flexbugs-fixes": "^5.0.2",
83 | "postcss-import": "^14.0.2",
84 | "postcss-loader": "^6.1.0",
85 | "postcss-object-fit-images": "^1.1.2",
86 | "postcss-preset-env": "^6.7.0",
87 | "prettier": "^2.3.2",
88 | "sass": "^1.35.1",
89 | "sass-loader": "^12.1.0",
90 | "shelljs": "^0.8.4",
91 | "style-loader": "^3.0.0",
92 | "stylelint": "^13.13.1",
93 | "stylelint-config-prettier": "^8.0.2",
94 | "stylelint-config-standard": "^22.0.0",
95 | "stylelint-order": "^4.1.0",
96 | "stylelint-prettier": "^1.2.0",
97 | "terser-webpack-plugin": "^5.1.4",
98 | "thread-loader": "^3.0.4",
99 | "typescript": "^4.2.4",
100 | "webpack": "^5.41.0",
101 | "webpack-bundle-analyzer": "^4.4.2",
102 | "webpack-dev-server": "^3.11.2",
103 | "webpack-merge": "^5.8.0",
104 | "yargs": "^17.0.1"
105 | },
106 | "engines": {
107 | "node": ">=12.13.0"
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: [
3 | require('postcss-import'),
4 | require('postcss-flexbugs-fixes'),
5 | require('autoprefixer'),
6 | require('postcss-preset-env'),
7 | require('postcss-object-fit-images'),
8 | ],
9 | };
10 |
--------------------------------------------------------------------------------
/scripts/build.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | /*
3 | 生产环境输出编译后文件
4 | */
5 |
6 | // 设置环境变量
7 | process.env.NODE_ENV = 'production';
8 |
9 | // promise reject 报错未 catch 的处理
10 | process.on('unhandledRejection', (err) => {
11 | throw err;
12 | });
13 |
14 | const { parseCommandLine } = require('./utils/parseCommandLine');
15 | const params = parseCommandLine();
16 |
17 | // 开始构建
18 | const shell = require('shelljs');
19 | const _ = require('lodash');
20 | const webpack = require('webpack');
21 | const chalk = require('chalk');
22 | const pathConfig = require('./config/paths.config');
23 | const webpackConfig = require('./config/webpack.prod.config');
24 | const { findDLLFile } = require('./utils/findDLLFile');
25 |
26 | const prodConfig = pathConfig(process.env.NODE_ENV);
27 |
28 | _.set(prodConfig, 'bundleAnalyzerReport', params['report']);
29 | _.set(prodConfig, 'dllGuide', findDLLFile(prodConfig, process.env.NODE_ENV))
30 |
31 | // 输出文件夹清空
32 | shell.rm('-rf', 'build');
33 |
34 | // loading
35 | console.log('building for production...');
36 |
37 | const compiler = webpack(webpackConfig(prodConfig));
38 |
39 | compiler.run((err, stats) => {
40 | if (err) {
41 | console.error(err);
42 | throw err;
43 | }
44 |
45 | // report 开启后不输出其他 stdout,否则会打断 report ,报出错误
46 | if (params['report']) return;
47 |
48 | // 编译结果输出
49 | process.stdout.write(
50 | stats.toString({
51 | colors: true,
52 | modules: false,
53 | children: false,
54 | chunks: false,
55 | chunkModules: false,
56 | }) + '\n\n',
57 | );
58 |
59 | if (stats.hasErrors()) {
60 | console.log(chalk.red(' Build failed with errors.\n'));
61 | process.exit(1);
62 | }
63 |
64 | console.log(chalk.cyan(' Build complete.\n'));
65 | // compiler.close();
66 | process.exit(0);
67 | })
68 |
69 |
--------------------------------------------------------------------------------
/scripts/config/devServer.config.js:
--------------------------------------------------------------------------------
1 | /*
2 | * dev-server 配置
3 | * */
4 |
5 | module.exports = (option) => {
6 | return {
7 | contentBase: option.buildPath,
8 | publicPath: option.publicPath,
9 | clientLogLevel: 'silent',
10 | hot: true,
11 | inline: true,
12 | compress: true,
13 | open: true,
14 | openPage: '.',
15 | port: option.customPort,
16 | host: option.customHost,
17 | https: option.customProtocol === 'https',
18 | proxy: option.customProxy,
19 | watchOptions: {
20 | ignored: /node_modules/,
21 | },
22 | stats: {
23 | colors: true,
24 | errors: true,
25 | warnings: true,
26 | modules: false,
27 | chunks: false,
28 | },
29 | disableHostCheck: true,
30 | };
31 | };
32 |
--------------------------------------------------------------------------------
/scripts/config/htmlPlugins.config.js:
--------------------------------------------------------------------------------
1 | /**
2 | * html 生成相关 webpack plugin 配置(包括 copyFile tag)
3 | * */
4 | const path = require('path');
5 | const _ = require('lodash');
6 | const chalk = require('chalk');
7 | const HtmlWebpackPlugin = require('html-webpack-plugin');
8 | const HtmlWebpackTagsPlugin = require('html-webpack-tags-plugin');
9 | const CopyWebpackPlugin = require('copy-webpack-plugin');
10 | const pkg = require('../../package.json');
11 |
12 | function configHtmlPlugin(currentConfig) {
13 | const dllGuide = currentConfig.dllGuide;
14 | const isDev = process.env.NODE_ENV !== 'production';
15 |
16 | /**
17 | * 这里将 core-js 做了一个单独的处理 -- copy 后全局引用
18 | * */
19 | let coreJsVersion = _.get(pkg, ['dependencies', 'core-js-bundle']);
20 |
21 | if (!coreJsVersion) {
22 | console.log(
23 | chalk.red('\n ERROR Must have "core-js-bundle" package in you package.json dependencies \n')
24 | );
25 | process.exit(1);
26 | }
27 | coreJsVersion = coreJsVersion.replace(/^\^/, '');
28 | const coreSource = path.join(currentConfig.context, 'node_modules/core-js-bundle/minified.js');
29 | const coreDest = path.join(currentConfig.dllStaticDir, `core-js@${coreJsVersion}.production.js`,);
30 | const patterns = [{ from: coreSource, to: coreDest }];
31 | const tags = [coreDest];
32 |
33 | isDev && patterns.push({
34 | from: path.join(currentConfig.context, 'node_modules/core-js-bundle/minified.js.map'),
35 | to: path.join(currentConfig.dllStaticDir, `minified.js.map`,)
36 | })
37 |
38 | if (dllGuide && dllGuide.hasDll) {
39 | dllGuide.dlls.map(dll => {
40 | patterns.push({
41 | from: path.join(currentConfig.context, 'dll', dll.filename),
42 | to: path.join(currentConfig.dllStaticDir, dll.filename),
43 | });
44 | dll.versionFile && patterns.push({
45 | from: path.join(currentConfig.context, 'dll', dll.versionFile),
46 | to: path.join(currentConfig.dllStaticDir, dll.versionFile),
47 | });
48 | isDev && patterns.push({
49 | from: path.join(currentConfig.context, 'dll', `${dll.filename}.map`),
50 | to: path.join(currentConfig.dllStaticDir, `${dll.filename}.map`),
51 | })
52 | tags.push(path.join(currentConfig.dllStaticDir, dll.filename));
53 | });
54 | }
55 | const htmlPlugins = [
56 | new HtmlWebpackPlugin({
57 | template: currentConfig.htmlTemplate,
58 | filename: 'index.html',
59 | templateParameters: currentConfig.htmlParameter,
60 | inject: true,
61 | xhtml: true,
62 | cache: false,
63 | minify: {
64 | collapseWhitespace: true,
65 | removeComments: true,
66 | removeRedundantAttributes: true,
67 | removeScriptTypeAttributes: true,
68 | removeStyleLinkTypeAttributes: true,
69 | useShortDoctype: true,
70 | removeEmptyAttributes: true,
71 | keepClosingSlash: true,
72 | minifyJS: true,
73 | minifyCSS: true,
74 | minifyURLs: true,
75 | },
76 | }),
77 | new CopyWebpackPlugin({ patterns }),
78 | new HtmlWebpackTagsPlugin({ tags, append: false, useHash: false }),
79 | ];
80 |
81 | return htmlPlugins;
82 | }
83 |
84 | module.exports = {configHtmlPlugin};
85 |
--------------------------------------------------------------------------------
/scripts/config/loaders.config.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Loaders plugin 配置
3 | * */
4 | const os = require('os');
5 | const path = require('path');
6 | const utils = require('../utils/tools');
7 | const _ = require('lodash');
8 | const threadLoader = require('thread-loader');
9 | const chalk = require('chalk');
10 | const MiniCssExtractPlugin = require('mini-css-extract-plugin');
11 |
12 | const cpuNumber = Math.min(Math.max(_.get(os.cpus(), 'length', 1) - 1, 1), 4);
13 | console.log(chalk.cyan(`Number of CPU core Used: ${cpuNumber}`));
14 |
15 | const jsWorkerPool = {
16 | workers: cpuNumber,
17 | poolTimeout: Infinity, // 设置为无穷大, 这样在监视模式(--watch)下可以保持 worker 持续存在
18 | };
19 |
20 | threadLoader.warmup(jsWorkerPool, [
21 | 'babel-loader',
22 | '@babel/preset-env',
23 | '@babel/preset-react',
24 | '@babel/preset-typescript',
25 | ]);
26 |
27 | module.exports = (currentConfig) => {
28 | const namedAssets = utils.resolve(currentConfig.staticDir);
29 | const isDev = process.env.NODE_ENV !== 'production';
30 |
31 | return [
32 | {
33 | test: /\.(js|jsx|ts|tsx)$/,
34 | include: currentConfig.sourceCode,
35 | exclude: /node_modules/,
36 | use: [
37 | {loader: 'thread-loader', options: jsWorkerPool},
38 | {loader: 'babel-loader', options: {
39 | exclude: [
40 | // \\ for Windows, / for macOS and Linux 排除不需要转义的包
41 | /node_modules[\\/]core-js/,
42 | /node_modules[\\/]webpack[\\/]buildin/,
43 | ],
44 | cacheDirectory: isDev ? path.join(currentConfig.cacheDir, 'babel-loader') : false
45 | }},
46 | ],
47 | },
48 | {
49 | test: /\.(scss)$/,
50 | include: currentConfig.sourceCode,
51 | use: [
52 | {loader: isDev ? 'style-loader' : MiniCssExtractPlugin.loader},
53 | {loader: 'css-loader'},
54 | {loader: 'postcss-loader'},
55 | {loader: 'sass-loader'},
56 | ],
57 | },
58 | {
59 | test: /\.css$/,
60 | include: [/node_modules/, currentConfig.sourceCode],
61 | use: [
62 | {loader: isDev ? 'style-loader' : MiniCssExtractPlugin.loader},
63 | {loader: 'css-loader'},
64 | {loader: 'postcss-loader'},
65 | ],
66 | },
67 | {
68 | test: /\.(png|svg|jpg|jpeg|gif)$/i,
69 | type: 'asset/resource',
70 | generator: {
71 | filename: namedAssets(isDev ? 'media/[name].[ext]' : 'media/[name].[hash:8].[ext]')
72 | }
73 | },
74 | {
75 | test: /\.(woff|woff2|eot|ttf|otf)$/i,
76 | type: 'asset/resource',
77 | generator: {
78 | filename: namedAssets(isDev ? 'fonts/[name].[ext]' : 'fonts/[name].[hash:8].[ext]')
79 | }
80 | },
81 | ];
82 | };
83 |
--------------------------------------------------------------------------------
/scripts/config/paths.config.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | /*
3 | 开发配置文件
4 | */
5 | const utils = require('../utils/tools');
6 | const resolve = utils.resolve(__dirname, '../../');
7 |
8 | module.exports = (NODE_ENV) => {
9 | const isDev = NODE_ENV === 'development';
10 | const vendorPackages = {
11 | vendor: [],
12 | };
13 | // dllPackages 有顺序
14 | const dllPackages = [
15 | {name: 'basic', packages: ['react','react-dom']},
16 | {name: 'tool', packages: ['lodash', 'axios']}
17 | ]
18 | const externals = [];
19 |
20 | return {
21 | context: resolve(''),
22 | sourceCode: resolve('src'),
23 | publicPath: '/',
24 | buildPath: resolve(isDev ? 'dev': 'build'),
25 | staticDir: 'static',
26 | dllStaticDir: 'static/dll',
27 | commonPath: resolve('src/common'),
28 | entryPath: resolve(`src/index.tsx`),
29 | htmlTemplate: resolve(`src/index.html`),
30 | reportPath: resolve(`report`),
31 | cacheDir: resolve(`node_modules/.cache`),
32 | htmlParameter: {}, // html 传的变量
33 | vendorPackages: vendorPackages,
34 | dllPackages: dllPackages,
35 | externals: externals,
36 | dllPath: resolve('dll'),
37 | bundleAnalyzerReport: false,
38 | dllGuide: {},
39 | alias: {
40 | store: resolve('src/store')
41 | },
42 | antdTheme: {},
43 | mfConfig: { // 模块联邦配置
44 | // remotes: {
45 | // 'app': 'app@http://localhost:3003/remoteEntry.js'
46 | // },
47 | // exposes: {
48 | // './base/GlobalContext': './base/GlobalContext'
49 | // },
50 | // shared: ['echarts']
51 | },
52 | proxy: {}, // dev-server 的代理接口
53 | webpackEnvironment: { // 定义那些es 新特性可以显示在打包后代码中
54 | arrowFunction: false,
55 | const: false,
56 | destructuring: false,
57 | forOf: false
58 | }
59 | }
60 | };
61 |
--------------------------------------------------------------------------------
/scripts/config/webpack.base.config.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | /*
3 | webapck 通用
4 | */
5 | const path = require('path');
6 | const _ = require('lodash');
7 | const webpack = require('webpack');
8 | const loadersConfig = require('./loaders.config');
9 | const {configHtmlPlugin} = require('./htmlPlugins.config');
10 | const utils = require('../utils/tools');
11 | const ModuleFederationPlugin = webpack.container.ModuleFederationPlugin;
12 |
13 | module.exports = (currentConfig) => {
14 | const namedAssets = utils.resolve(currentConfig.staticDir);
15 | const isDev = process.env.NODE_ENV !== 'production';
16 | const rules = loadersConfig(currentConfig);
17 | const htmlPlugins = configHtmlPlugin(currentConfig);
18 | const { vendor } = currentConfig.vendorPackages;
19 | const dllGuide = currentConfig.dllGuide;
20 | let dllPlugins = [];
21 |
22 | if (dllGuide && dllGuide.hasDll) {
23 | dllPlugins = dllGuide.dlls.map(dll => new webpack.DllReferencePlugin({
24 | context: currentConfig.context,
25 | manifest: require(path.resolve(currentConfig.dllPath, dll.manifest)),
26 | name: `dll_${dll.name}`,
27 | }));
28 | }
29 |
30 | return {
31 | context: currentConfig.context,
32 | entry: {
33 | main: currentConfig.entryPath,
34 | },
35 | target: 'web',
36 | output: {
37 | pathinfo: isDev,
38 | clean: false, // 交给外部处理
39 | path: currentConfig.buildPath,
40 | publicPath: currentConfig.publicPath,
41 | filename: namedAssets(isDev ? 'js/[name].js' : 'js/[name].[contenthash:6].js'),
42 | chunkFilename: namedAssets(isDev ? 'chunk/[name].js' : 'chunk/[name].[contenthash:6].js'),
43 | environment: currentConfig.webpackEnvironment,
44 | },
45 | resolve: {
46 | extensions: ['.ts', '.tsx', '.js', '.scss'], // 尽量的减少条目,这样可以减少文件系统的调用次数
47 | modules: ['node_modules', currentConfig.sourceCode],
48 | alias: currentConfig.alias || {},
49 | symlinks: false,
50 | },
51 | // 性能提示,打包文件过大不提示 warning
52 | performance: {
53 | hints: false,
54 | },
55 | optimization: {
56 | chunkIds: isDev ? 'named' : 'deterministic',
57 | moduleIds: isDev ? 'named' : 'deterministic',
58 | splitChunks: {
59 | // 提取规则
60 | cacheGroups: {
61 | mainJS: {
62 | chunks: 'initial',
63 | minChunks: 2,
64 | name: 'main',
65 | maxInitialRequests: 5,
66 | minSize: 0,
67 | },
68 | vendor: {
69 | test: new RegExp(`[\\\\/]node_modules[\\\\/](${vendor.join('|')})[\\\\/]`),
70 | priority: 1,
71 | chunks: 'all',
72 | name: 'vendor',
73 | enforce: true,
74 | },
75 | styles: {
76 | name: 'main-style',
77 | type: 'css/mini-extract',
78 | chunks: 'all',
79 | enforce: true,
80 | },
81 | default: {
82 | minSize: 100000,
83 | minChunks: 2,
84 | },
85 | },
86 | },
87 | runtimeChunk: false, // MF 报错
88 | },
89 | module: {
90 | // 使缺少的导出报 error 而不是 warning
91 | strictExportPresence: true,
92 | // noParse: /lodash|moment|validator|qs|immutable/, // MF 报错
93 | rules: rules,
94 | },
95 | plugins: [
96 | // 全局常量配置
97 | new webpack.DefinePlugin({
98 | RUNTIME_NODE_ENV: JSON.stringify(process.env.NODE_ENV),
99 | }),
100 | // 自动加载模块而不必导出 import
101 | new webpack.ProvidePlugin({
102 | React: 'react',
103 | ReactDOM: 'react-dom',
104 | _: 'lodash',
105 | immer: 'immer'
106 | }),
107 | // 忽略对某些模块的打包
108 | new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
109 | ...(_.isEmpty(currentConfig.mfConfig) ? [] : [new ModuleFederationPlugin(currentConfig.mfConfig)]),
110 | ...dllPlugins,
111 | ...htmlPlugins,
112 | ],
113 | };
114 | };
115 |
--------------------------------------------------------------------------------
/scripts/config/webpack.dev.config.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | /**
3 | * development 环境下 webpack 配置文件
4 | * NOTICE: 考虑到随着业务搭建,可能会有更多的 webpack 配置,这里暂时不与 webpack.base.config 合并
5 | * */
6 |
7 | const path = require('path');
8 | const {merge} = require('webpack-merge');
9 | const ESLintWebpackPlugin = require('eslint-webpack-plugin');
10 | const baseWebpackConfig = require('./webpack.base.config');
11 |
12 | module.exports = (devConfig) => {
13 | const baseDevWebpackConfig = baseWebpackConfig(devConfig);
14 | // hot reload 暂时禁止使用
15 |
16 | return merge(baseDevWebpackConfig, {
17 | mode: 'development',
18 | devtool: 'eval-cheap-module-source-map',
19 | entry: {
20 | main: devConfig.entryPath,
21 | },
22 | cache: {
23 | type: 'filesystem', // filesystem 缓存在文件系统,这样下次编译会有缓存的性能加成
24 | cacheDirectory: path.join(devConfig.cacheDir, 'webpack'), // cache 存放地址
25 | store: 'pack', // 设置编译器闲置时存放
26 | buildDependencies: {
27 | config: [devConfig.context] // 依赖项地址
28 | }
29 | },
30 | // externals: devConfig.externals,
31 | plugins: [
32 | // ...(devConfig.isHotReload ? [new webpack.HotModuleReplacementPlugin()] : []),
33 | new ESLintWebpackPlugin({
34 | lintDirtyModulesOnly: true, // 仅检查变更文件,首次 start 不校验
35 | threads: true, // 开启多线程
36 | formatter: 'stylish', // 报错输出格式化
37 | }),
38 | ],
39 | });
40 | };
41 |
--------------------------------------------------------------------------------
/scripts/config/webpack.dll.config.js:
--------------------------------------------------------------------------------
1 | /**
2 | * react 相关的动态链接库 DLL
3 | * */
4 | const path = require('path');
5 | const _ = require('lodash');
6 | const chalk = require('chalk');
7 | const webpack = require('webpack');
8 | const TerserPlugin = require("terser-webpack-plugin");
9 | const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
10 |
11 | module.exports = (env, currentConfig) => {
12 | if (!['development', 'production'].includes(env)) {
13 | console.log(chalk.red(' The environment must be `development` or `production` .\n'));
14 | process.exit(1);
15 | }
16 |
17 | process.env.NODE_ENV = env;
18 | const isDev = env === 'development';
19 | const dllPackages = currentConfig.dllPackages;
20 |
21 | if (!_.isArray(dllPackages) || _.isEmpty(dllPackages)) {
22 | console.log(
23 | chalk.red(
24 | ' The `dllPackages` is needed, set dllPackages in loaders.config.js .\n',
25 | ),
26 | );
27 | process.exit(1);
28 | }
29 |
30 | return {
31 | mode: env,
32 | entry: dllPackages.reduce((p, c) => ({...p, [c.name]: c.packages}), {}),
33 | performance: { hints: false },
34 | devtool: isDev ? 'source-map' : false, // 开发环境配置 sourceMap 方便 debug
35 | output: {
36 | filename: `dll_[name]_[contenthash:6].${env}.js`,
37 | library: 'dll_[name]',
38 | // clean: true, // 不能打开 clean ,因为 dll 会构建两个版本 dev prod, clean 会将其中一个删掉
39 | path: currentConfig.dllPath,
40 | environment: currentConfig.webpackEnvironment,
41 | devtoolModuleFilenameTemplate: 'webpack:///[resource-path]?[loaders]',
42 | },
43 | optimization: {
44 | minimize: true,
45 | minimizer: [
46 | new TerserPlugin({
47 | parallel: true, // 开启多进程
48 | terserOptions: {
49 | sourceMap: true,
50 | format: {comments: false}
51 | },
52 | extractComments: false
53 | })
54 | ],
55 | chunkIds: 'named',
56 | moduleIds: 'named',
57 | },
58 | plugins: [
59 | new webpack.DllPlugin({
60 | path: path.join(currentConfig.dllPath, `[name]_manifest_${env}.json`),
61 | name: 'dll_[name]',
62 | context: currentConfig.context,
63 | }),
64 | ...(env === 'production'
65 | ? [
66 | new BundleAnalyzerPlugin({
67 | analyzerMode: 'static',
68 | analyzerHost: '127.0.0.1',
69 | analyzerPort: 8887,
70 | reportFilename: `${currentConfig.context}/report/dll/report.html`,
71 | defaultSizes: 'parsed',
72 | openAnalyzer: false,
73 | generateStatsFile: true,
74 | statsFilename: `${currentConfig.context}/report/dll/stats.json`,
75 | statsOptions: null,
76 | logLevel: 'info',
77 | }),
78 | ]
79 | : []),
80 | ],
81 | };
82 | };
83 |
--------------------------------------------------------------------------------
/scripts/config/webpack.prod.config.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | /*
4 | production 环境下 webpack 配置文件
5 | */
6 |
7 | const {merge} = require('webpack-merge');
8 | const MiniCssExtractPlugin = require('mini-css-extract-plugin');
9 | const ESLintWebpackPlugin = require('eslint-webpack-plugin');
10 | const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
11 | const baseWebpackConfig = require('./webpack.base.config');
12 | const utils = require('../utils/tools');
13 |
14 | module.exports = (prodConfig) => {
15 | const namedAssets = utils.resolve(prodConfig.staticDir);
16 | const reportPlugin = [];
17 | const baseProdConfig = baseWebpackConfig(prodConfig);
18 |
19 | if (prodConfig.bundleAnalyzerReport) {
20 | const {BundleAnalyzerPlugin} = require('webpack-bundle-analyzer');
21 |
22 | reportPlugin.push(
23 | new BundleAnalyzerPlugin({
24 | analyzerMode: 'static',
25 | analyzerHost: '127.0.0.1',
26 | analyzerPort: 8888,
27 | reportFilename: `${prodConfig.reportPath}/${process.env.NODE_ENV}/report.html`,
28 | defaultSizes: 'parsed',
29 | openAnalyzer: false,
30 | generateStatsFile: true,
31 | statsFilename: `${prodConfig.reportPath}/${process.env.NODE_ENV}/stats.json`,
32 | statsOptions: null,
33 | logLevel: 'info',
34 | }),
35 | );
36 | }
37 |
38 | return merge(baseProdConfig, {
39 | mode: 'production',
40 | devtool: false,
41 | optimization: {
42 | ...baseProdConfig.optimization,
43 | minimize: true,
44 | minimizer: [
45 | `...`, // 不可删,webpack 5 提供,代表集成默认的 minimizer 配置
46 | new CssMinimizerPlugin({
47 | minimizerOptions: {
48 | preset: ['default', {discardComments: { removeAll: true }}],
49 | },
50 | }),
51 | ]
52 | },
53 | bail: true, // 在第一个错误出错时抛出,而不是无视错误。
54 | cache: false, // prod 禁用缓存
55 | // externals: prodConfig.externals,
56 | plugins: [
57 | new MiniCssExtractPlugin({
58 | ignoreOrder: true,
59 | filename: namedAssets('css/[name].[contenthash:6].css'),
60 | chunkFilename: namedAssets('css/[name].[contenthash:6].css'),
61 | // insert: '#some-element' // 表示将生成的 link 标签插入到id=some-element 的元素后边
62 | }),
63 | new ESLintWebpackPlugin({
64 | lintDirtyModulesOnly: false, // prod build 检查所有文件
65 | threads: true, // 开启多线程
66 | formatter: 'stylish', // 报错输出格式化
67 | }),
68 | ...reportPlugin,
69 | ],
70 | });
71 | };
72 |
--------------------------------------------------------------------------------
/scripts/dll-version-check.js:
--------------------------------------------------------------------------------
1 | /**
2 | * pre-commit 检查 DLL 的依赖是否有版本变化
3 | * */
4 | const fs = require('fs');
5 | const path = require('path');
6 | const chalk = require('chalk');
7 | const pathConfig = require('./config/paths.config');
8 | const {findDLLFile} = require('./utils/findDLLFile');
9 | const pkg = require('../package.json');
10 |
11 | const prodConfig = pathConfig('production');
12 | const dllGuide = findDLLFile(prodConfig, 'production');
13 |
14 | if (dllGuide.hasDll) {
15 | const dependencies = pkg.dependencies;
16 | const versionChanged = [];
17 | dllGuide.dlls.forEach(dll => {
18 | if (dll.versionFile) {
19 | try {
20 | const versionTxt = fs.readFileSync(path.join(prodConfig.dllPath, dll.versionFile), 'utf8');
21 | const versionJson = JSON.parse(versionTxt);
22 | Object.keys(versionJson).forEach((packageName) => {
23 | if (versionJson[packageName] !== dependencies[packageName]) {
24 | versionChanged.push(packageName);
25 | }
26 | })
27 | } catch (e) {
28 | throw e;
29 | }
30 | }
31 | });
32 | if (versionChanged.length > 0) {
33 | console.log(chalk.yellow(`
34 | The dependent version of the DLL is updated "${versionChanged.join(', ')}"
35 | You need to rerun the script "npm run build:dll"
36 | `));
37 | process.exit(1);
38 | } else {
39 | console.log(chalk.yellow(`\n The DLL dependency version check passed \n`));
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/scripts/dll.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | /*
4 | * dll 生成脚本
5 | * */
6 |
7 | // promise reject 报错未 catch 的处理
8 | process.on('unhandledRejection', (err) => {
9 | throw err;
10 | });
11 |
12 | const webpack = require('webpack');
13 | const chalk = require('chalk');
14 | const shell = require('shelljs');
15 | const {writeDLLVersion} = require('./utils/findDLLFile');
16 | const pkg = require('../package.json');
17 | const dllConfig = require('./config/webpack.dll.config');
18 | const pathConfig = require('./config/paths.config');
19 |
20 | // 文件夹清空
21 | shell.rm('-rf', 'dll');
22 |
23 | // dev prod 同时编译
24 | const devConfig = pathConfig('development');
25 | const prodConfig = pathConfig('production');
26 |
27 | const compiler = webpack([
28 | dllConfig('development', devConfig),
29 | dllConfig('production', prodConfig),
30 | ]);
31 |
32 | compiler.run((err, stats) => {
33 | if (err) {
34 | console.error(err);
35 | throw err;
36 | }
37 |
38 | // 输出 DLL 依赖版本
39 | writeDLLVersion(prodConfig, 'production', pkg);
40 |
41 | // 编译结果输出
42 | process.stdout.write(
43 | stats.toString({
44 | colors: true,
45 | modules: false,
46 | children: false,
47 | chunks: false,
48 | chunkModules: false,
49 | }) + '\n\n',
50 | );
51 |
52 | if (stats.hasErrors()) {
53 | console.log(chalk.red(' Build failed with errors.\n'));
54 | process.exit(1);
55 | }
56 | if (
57 | stats.hasWarnings() &&
58 | process.env.CI &&
59 | (typeof process.env.CI !== 'string' || process.env.CI.toLowerCase() !== 'false')
60 | ) {
61 | console.log(
62 | chalk.yellow(
63 | '\nTreating warnings as errors because process.env.CI = true.\n' +
64 | 'Most CI servers set it automatically.\n',
65 | ),
66 | );
67 | process.exit(1);
68 | }
69 | compiler.close();
70 | })
71 |
--------------------------------------------------------------------------------
/scripts/start.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | /*
4 | * npm start ...
5 | * */
6 |
7 | // 设置环境变量
8 | process.env.NODE_ENV = 'development';
9 |
10 | // promise reject 报错未 catch 的处理
11 | process.on('unhandledRejection', (err) => {
12 | throw err;
13 | });
14 |
15 | const { parseCommandLine } = require('./utils/parseCommandLine');
16 | const params = parseCommandLine();
17 |
18 | // 开始构建
19 | const _ = require('lodash');
20 | const webpack = require('webpack');
21 | const WebpackDevServer = require('webpack-dev-server');
22 | const pathConfig = require('./config/paths.config');
23 | const webpackConfig = require('./config/webpack.dev.config');
24 | const devServerConfig = require('./config/devServer.config');
25 | const {findDLLFile} = require('./utils/findDLLFile');
26 |
27 | const devConfig = pathConfig(process.env.NODE_ENV);
28 |
29 | // webpack 的配置替换
30 | _.set(devConfig, 'dllGuide', findDLLFile(devConfig, process.env.NODE_ENV));
31 |
32 | startServer();
33 |
34 | function startServer() {
35 | const customPort = parseInt(params['port'], 10) || 3032;
36 | const customHost = process.env.HOST || '0.0.0.0';
37 | const customProtocol = process.env.HTTPS === 'true' ? 'https' : 'http';
38 | const compiler = webpack(webpackConfig(devConfig));
39 | const devServerOptions = devServerConfig({
40 | buildPath: devConfig.buildPath,
41 | publicPath: devConfig.publicPath,
42 | customPort,
43 | customHost,
44 | customProtocol,
45 | customProxy: devConfig.proxy,
46 | });
47 |
48 | const server = new WebpackDevServer(compiler, devServerOptions);
49 |
50 | server.listen(customPort, customHost);
51 | }
52 |
--------------------------------------------------------------------------------
/scripts/utils/findDLLFile.js:
--------------------------------------------------------------------------------
1 | /**
2 | * DLL 文件识别
3 | * */
4 |
5 | const fs = require('fs');
6 | const path = require('path');
7 | const chalk = require('chalk');
8 | const _ = require('lodash');
9 |
10 | function findDLLFile(currentConfig, env) {
11 | const dllGuide = {
12 | hasDll: true,
13 | dlls: []
14 | };
15 |
16 | try {
17 | const files = fs.readdirSync(currentConfig.dllPath);
18 | const dllPackages = currentConfig.dllPackages;
19 | if (!_.isArray(dllPackages) || dllPackages.length === 0) {
20 | dllGuide.hasDll = false;
21 | } else {
22 | dllGuide.dlls = dllPackages.map(d => findDLLFileItem({env, entryName: d.name, files}))
23 | }
24 | } catch (e) {}
25 |
26 | if (!dllGuide.hasDll || dllGuide.dlls.length === 0 || dllGuide.dlls.some(d => !d.hasDll)) {
27 | dllGuide.hasDll = false;
28 | console.log(
29 | chalk.bgYellow.black('\n WARNING ') +
30 | chalk.yellow(' Can not find DLL files, please check `/dll` directory \n')
31 | );
32 | }
33 | return dllGuide;
34 | }
35 |
36 | function findDLLFileItem({env, entryName, files}) {
37 | const dllGuide = {
38 | hasDll: true,
39 | manifest: '',
40 | name: entryName,
41 | filename: '',
42 | versionFile: '',
43 | };
44 |
45 | if (Array.isArray(files)) {
46 | files.forEach((file) => {
47 | if (!file) return;
48 | if (env === 'production') {
49 | if (file === `${entryName}_manifest_production.json`) {
50 | return dllGuide.manifest = `${entryName}_manifest_production.json`;
51 | }
52 | const prodNameMatch = file.match(new RegExp(`^dll_${entryName}_[a-zA-Z0-9]{6}\\.production\\.js$`));
53 | if (Array.isArray(prodNameMatch) && prodNameMatch[0]) {
54 | dllGuide.filename = prodNameMatch[0];
55 | }
56 | const prodVersionMatch = file.match(new RegExp(`^dll_${entryName}_[a-zA-Z0-9]{6}\\.production\\.js\\.VERSION\\.txt$`));
57 | if (Array.isArray(prodVersionMatch) && prodVersionMatch[0]) {
58 | dllGuide.versionFile = prodVersionMatch[0];
59 | }
60 | } else {
61 | if (file === `${entryName}_manifest_development.json`) {
62 | return dllGuide.manifest = `${entryName}_manifest_development.json`;
63 | }
64 | const devNameMatch = file.match(new RegExp(`^dll_${entryName}_[a-zA-Z0-9]{6}\\.development\\.js$`));
65 | if (Array.isArray(devNameMatch) && devNameMatch[0]) {
66 | dllGuide.filename = devNameMatch[0];
67 | }
68 | }
69 | });
70 | }
71 |
72 | if (!dllGuide.filename || !dllGuide.manifest) {
73 | dllGuide.hasDll = false;
74 | }
75 |
76 | return dllGuide;
77 | }
78 |
79 | function writeDLLVersion(currentConfig, env, pkg) {
80 | const dllPackages = currentConfig.dllPackages;
81 | const dependencies = pkg.dependencies;
82 | // prodDll 顺序与 dllPackages 的顺序是一致的
83 | const prodDll = findDLLFile(currentConfig, env);
84 | if (prodDll.hasDll) {
85 | prodDll.dlls.forEach(({name, filename}, idx) => {
86 | const versions = (dllPackages[idx].packages || []).reduce((prev, p) => {
87 | prev[p] = dependencies[p] || '';
88 | return prev;
89 | }, {});
90 | fs.writeFileSync(
91 | path.join(currentConfig.dllPath, `${filename}.VERSION.txt`),
92 | JSON.stringify(versions, null, 2)
93 | )
94 | })
95 | }
96 | }
97 |
98 |
99 | module.exports = { findDLLFile, writeDLLVersion };
100 |
--------------------------------------------------------------------------------
/scripts/utils/parseCommandLine.js:
--------------------------------------------------------------------------------
1 | const yargs = require('yargs');
2 |
3 | function parseCommandLine() {
4 | const processArgvs = process.argv.slice(2);
5 |
6 | if (!processArgvs) return {};
7 |
8 | yargs(processArgvs).options({
9 | port: { alias: 'p', describe: '端口号' },
10 | report: { alias: 'r', describe: '打包后是否生成report(只适用于npm build)' },
11 | });
12 |
13 | return yargs.help().argv;
14 | }
15 |
16 | module.exports = { parseCommandLine };
17 |
--------------------------------------------------------------------------------
/scripts/utils/tools.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 |
3 | module.exports = {
4 | resolve: function (...basicPath) {
5 | return function (dir) {
6 | return path.join(...basicPath, dir || '');
7 | };
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/bootstrap.tsx:
--------------------------------------------------------------------------------
1 | import './store/initImmer';
2 | import { HashRouter } from 'react-router-dom';
3 | import { Provider } from 'react-redux';
4 | import RootContainer from './modules/root/routes';
5 | import store from './store';
6 |
7 | ReactDOM.render(
8 |
9 | loading...}>
10 |
11 |
12 |
13 |
14 | ,
15 | document.getElementById('root'),
16 | );
17 |
--------------------------------------------------------------------------------
/src/components/DynamicSystem/index.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块联邦 异步加载远程应用
3 | * */
4 |
5 | // 远程应用装载
6 | function loadComponent(scope: string, module: string) {
7 | return async () => {
8 | // 1. 初始化共享作用域
9 | await __webpack_init_sharing__('default');
10 | // 3. 拿到远程应用的容器(如果加载了一个 remote 的 remoteEntry.js 那么 remoteEntry.j 中会在 window 下注册容器)
11 | const container = window[scope];
12 | // 4. 初始化远程应用容器
13 | await container.init(__webpack_share_scopes__.default);
14 | // 5. 拿到远程应用容器中的模块
15 | const factory = await window[scope].get(module);
16 | const Module = factory();
17 | return Module;
18 | };
19 | }
20 |
21 | // 一个添加 remoteEntry.js 的自定义 HOOK
22 | function useDynamicRemoteEntry(remoteUrl: string) {
23 | const [ready, setReady] = React.useState(false);
24 | const [failed, setFailed] = React.useState(false);
25 |
26 | React.useEffect(() => {
27 | if (!remoteUrl) return undefined;
28 |
29 | const element = document.createElement('script');
30 |
31 | element.src = remoteUrl;
32 | element.type = 'text/javascript';
33 | element.async = true;
34 |
35 | setReady(false);
36 | setFailed(false);
37 |
38 | element.onload = () => {
39 | setReady(true);
40 | };
41 |
42 | element.onerror = () => {
43 | console.error(`Dynamic Script Error: ${remoteUrl}`);
44 | setReady(false);
45 | setFailed(true);
46 | };
47 |
48 | document.head.appendChild(element);
49 |
50 | return () => {
51 | document.head.removeChild(element);
52 | };
53 | }, [remoteUrl]);
54 |
55 | return {
56 | ready,
57 | failed,
58 | };
59 | }
60 |
61 | // 动态远程应用的渲染封装
62 | interface DynamicRemoteProps {
63 | remoteUrl: string;
64 | scope: string;
65 | module: string;
66 | [key: string]: any;
67 | }
68 | const DynamicSystem: React.FC = (props: DynamicRemoteProps) => {
69 | const { remoteUrl, module, scope, ...otherProps } = props;
70 | const { ready, failed } = useDynamicRemoteEntry(remoteUrl);
71 | if (!remoteUrl || !module || !scope) return null;
72 |
73 | if (!ready) {
74 | return Loading dynamic script: {remoteUrl}
;
75 | }
76 |
77 | if (failed) {
78 | return Failed to load dynamic script: {remoteUrl}
;
79 | }
80 |
81 | const Component = React.lazy(loadComponent(scope, module));
82 |
83 | return (
84 |
85 |
86 |
87 | );
88 | };
89 |
90 | export default DynamicSystem;
91 |
--------------------------------------------------------------------------------
/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | title
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/index.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * 如果 mfConfig.exposes 有配置则需要使用 import('./bootstrap');
3 | * */
4 | // import('./bootstrap');
5 | import './bootstrap';
6 |
--------------------------------------------------------------------------------
/src/modules/remote/Cache.tsx:
--------------------------------------------------------------------------------
1 | interface Props {
2 | cache: {
3 | remoteUrl: string;
4 | scope: string;
5 | module: string;
6 | }[];
7 | }
8 |
9 | class Cache extends React.PureComponent {
10 | render(): React.ReactNode {
11 | const { cache } = this.props;
12 | console.log('render cache');
13 |
14 | return (
15 |
16 | {cache.map((c) => {
17 | return (
18 |
19 |
CACHE scope: {c.scope}
20 |
CACHE remoteUrl: {c.remoteUrl}
21 |
CACHE module: {c.module}
22 |
23 | );
24 | })}
25 |
26 | );
27 | }
28 | }
29 |
30 | export default Cache;
31 |
--------------------------------------------------------------------------------
/src/modules/remote/Content.tsx:
--------------------------------------------------------------------------------
1 | interface Props {
2 | content: {
3 | remoteUrl: string;
4 | scope: string;
5 | module: string;
6 | };
7 | }
8 |
9 | class Content extends React.PureComponent {
10 | render(): React.ReactNode {
11 | const { content } = this.props;
12 | console.log('render content');
13 |
14 | return (
15 |
16 |
CONTENT scope: {content.scope}
17 |
CONTENT remoteUrl: {content.remoteUrl}
18 |
CONTENT module: {content.module}
19 |
20 | );
21 | }
22 | }
23 |
24 | export default Content;
25 |
--------------------------------------------------------------------------------
/src/modules/remote/index.tsx:
--------------------------------------------------------------------------------
1 | import { Button, Form, Input } from 'antd';
2 | import { connect } from 'react-redux';
3 | import { actions, RootState, STORE_NAMES } from 'store';
4 | import Cache from './Cache';
5 | import Content from './Content';
6 | // import DynamicSystem from '../../components/DynamicSystem';
7 |
8 | const remoteActions = actions[STORE_NAMES.REMOTE];
9 |
10 | interface Props {
11 | remoteStore: RootState[STORE_NAMES.REMOTE];
12 | }
13 |
14 | class DynamicRemote extends React.Component {
15 | componentDidMount() {
16 | remoteActions.getData();
17 | }
18 |
19 | onFinish = (values: RootState[STORE_NAMES.REMOTE]['remote']['data']) => {
20 | remoteActions.updateStore((state) => {
21 | state.remote.data = values;
22 | });
23 | };
24 |
25 | cacheTo = () => {
26 | remoteActions.updateStore((state) => {
27 | state.remote.cache.push(state.remote.data);
28 | });
29 | };
30 |
31 | increase = () => {
32 | remoteActions.increase();
33 | };
34 |
35 | render(): React.ReactNode {
36 | const { remoteStore } = this.props;
37 | const { remote, count } = remoteStore;
38 | const { cache, data } = remote;
39 |
40 | console.log('render remote');
41 | return (
42 |
43 |
44 |
45 |
46 |
count: {count}
47 |
48 |
49 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
63 |
64 |
65 |
66 | {/* */}
72 |
73 |
74 | );
75 | }
76 | }
77 |
78 | const mapStateToProps = (state: RootState) => {
79 | return {
80 | remoteStore: state.remote,
81 | };
82 | };
83 |
84 | export default connect(mapStateToProps)(DynamicRemote);
85 |
--------------------------------------------------------------------------------
/src/modules/remote/remoteSlice.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Slice 结合了 action 与 reduce 的能力
3 | * */
4 | import { STORE_NAMES } from 'store';
5 | import { BaseSlice, createSubSlice } from '../../store/createSlice';
6 |
7 | interface InitialState {
8 | count: number;
9 | remote: {
10 | data: { remoteUrl: string; scope: string; module: string };
11 | cache: { remoteUrl: string; scope: string; module: string }[];
12 | };
13 | }
14 |
15 | class HomeSlice extends BaseSlice {
16 | storeName = STORE_NAMES.REMOTE;
17 | constructor() {
18 | // 通过 super() 传入初始数据
19 | super({
20 | count: 0,
21 | remote: {
22 | data: { remoteUrl: '', scope: '', module: '' },
23 | cache: [],
24 | },
25 | });
26 | }
27 |
28 | increase() {
29 | console.log(this.store);
30 | console.log(this.currentState);
31 | console.log(this.state);
32 | // Slice 内通过 this.updateStore() 来更新 state
33 | this.updateStore((state) => {
34 | // updateStore 参数函数内,实际就是 Immer 的 produce,
35 | // 在这里可以直接操作数据,而不用结构,Immer 会帮助生成新的不可变数据
36 | state.count += 1;
37 | });
38 |
39 | // Slice 内通过 this.resetStore() 来重置 state
40 | }
41 |
42 | getData() {
43 | return new Promise((resolve) => {
44 | setTimeout(
45 | () => resolve({ remoteUrl: 'default', scope: 'default', module: 'default' }),
46 | 3000,
47 | );
48 | }).then((cache: InitialState['remote']['data']) => {
49 | this.updateStore((state) => {
50 | state.remote.cache.push(cache);
51 | });
52 | });
53 | }
54 | }
55 |
56 | export default createSubSlice(new HomeSlice());
57 |
--------------------------------------------------------------------------------
/src/modules/root/routes.tsx:
--------------------------------------------------------------------------------
1 | import { Route, Switch, Redirect, Link } from 'react-router-dom';
2 | import { Button } from 'antd';
3 | import './styles/root.scss';
4 | import Remote from '../remote';
5 |
6 | const RouteEntry: React.FC = () => {
7 | const [state, setState] = React.useState({
8 | title: '',
9 | age: 0,
10 | });
11 |
12 | const reset = () => {
13 | setState(
14 | immer.produce((draft: Immer.Draft) => {
15 | draft.title = 'new title';
16 | }),
17 | );
18 | };
19 | console.log(state);
20 | return (
21 |
22 | } />
23 |
24 | (
28 |
29 |
30 | /remote
31 |
32 | )}
33 | />
34 |
35 | );
36 | };
37 |
38 | export default RouteEntry;
39 |
--------------------------------------------------------------------------------
/src/modules/root/styles/root.scss:
--------------------------------------------------------------------------------
1 | .root-login {
2 | position: relative;
3 | display: flex;
4 | flex-direction: column;
5 | width: 400px;
6 | height: 400px;
7 | border: 1px saddlebrown solid;
8 | align-items: center;
9 | justify-content: center;
10 | }
11 |
--------------------------------------------------------------------------------
/src/store/StoreNames.ts:
--------------------------------------------------------------------------------
1 | enum STORE_NAMES {
2 | REMOTE = 'remote',
3 | }
4 |
5 | export default STORE_NAMES;
6 |
--------------------------------------------------------------------------------
/src/store/createSlice.ts:
--------------------------------------------------------------------------------
1 | import { createSlice, PayloadAction, Store } from '@reduxjs/toolkit';
2 |
3 | type TUpdateFn = (state: Immer.Draft) => void;
4 |
5 | // eslint-disable-next-line @typescript-eslint/ban-types
6 | abstract class BaseSlice {
7 | public store: Store;
8 | abstract storeName: string;
9 | public initialState: State;
10 | public updateStore: (updateFn: Partial | TUpdateFn) => void;
11 | public resetStore: () => void;
12 |
13 | constructor(initialState: State) {
14 | this.initialState = initialState;
15 | }
16 |
17 | public get state() {
18 | return this.store.getState();
19 | }
20 |
21 | public get currentState() {
22 | const state = this.state;
23 | return state[this.storeName];
24 | }
25 | }
26 |
27 | // eslint-disable-next-line @typescript-eslint/ban-types
28 | function createSubSlice(sliceInstance: SI) {
29 | const { storeName, initialState } = sliceInstance;
30 |
31 | const slice = createSlice({
32 | name: storeName,
33 | initialState: initialState as IState,
34 | reducers: {
35 | updateStore: (
36 | state: Immer.Draft,
37 | action: PayloadAction<{ updateFn: TUpdateFn }>,
38 | ) => {
39 | return action.payload.updateFn(state);
40 | },
41 | resetStore: (state: Immer.Draft) => {
42 | Object.keys(initialState).forEach((key: string) => {
43 | state[key] = initialState[key];
44 | });
45 | },
46 | },
47 | });
48 |
49 | const { updateStore, resetStore } = slice.actions;
50 |
51 | sliceInstance.updateStore = function (param: Partial | TUpdateFn) {
52 | if (typeof param === 'function') {
53 | this.store.dispatch(updateStore({ updateFn: param }));
54 | } else {
55 | this.store.dispatch(
56 | updateStore({
57 | updateFn: (state) => {
58 | Object.keys(param).forEach((key: string) => {
59 | state[key] = param[key];
60 | });
61 | },
62 | }),
63 | );
64 | }
65 | };
66 |
67 | sliceInstance.resetStore = function () {
68 | this.store.dispatch(resetStore());
69 | };
70 |
71 | return {
72 | reducer: slice.reducer,
73 | sliceInstance,
74 | };
75 | }
76 |
77 | export { BaseSlice, createSubSlice };
78 |
--------------------------------------------------------------------------------
/src/store/createStore.ts:
--------------------------------------------------------------------------------
1 | import {
2 | configureStore,
3 | ConfigureStoreOptions,
4 | getDefaultMiddleware,
5 | Store,
6 | } from '@reduxjs/toolkit';
7 | import { Action, AnyAction, Reducer, ReducersMapObject } from 'redux';
8 | import { BaseSlice, createSubSlice } from './createSlice';
9 |
10 | // 给每一个 Slice 注入 store
11 | function beforeMountStore(store: Store) {
12 | function mountStoreToSlice(sliceInstance: SI): SI {
13 | sliceInstance.store = store;
14 | return sliceInstance;
15 | }
16 |
17 | return { mountStoreToSlice };
18 | }
19 |
20 | /**
21 | * 默认的 middleware 中 serializableCheck 会带来封装代码的报错:
22 | * "不让传 函数给 redux state" 实际上我们传入的函数只是个中间态,不会挂载到 state 上
23 | * 所以这里将他关掉
24 | * */
25 | function createStore(options: {
26 | reducer: Reducer | ReducersMapObject;
27 | devTools?: boolean | ConfigureStoreOptions['devTools'];
28 | }) {
29 | const { reducer, devTools } = options;
30 | return configureStore({
31 | reducer,
32 | devTools,
33 | middleware: getDefaultMiddleware({
34 | serializableCheck: false,
35 | }),
36 | });
37 | }
38 |
39 | export { beforeMountStore, createStore, BaseSlice, createSubSlice };
40 |
--------------------------------------------------------------------------------
/src/store/index.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块 store 创建
3 | * */
4 |
5 | import { createStore, beforeMountStore } from './createStore';
6 | import STORE_NAMES from './StoreNames';
7 | import remoteSlice from '../modules/remote/remoteSlice';
8 |
9 | const store = createStore({
10 | reducer: {
11 | [STORE_NAMES.REMOTE]: remoteSlice.reducer,
12 | },
13 | });
14 |
15 | export type RootState = ReturnType;
16 | // Inferred type: {posts: PostsState, comments: CommentsState, users: UsersState}
17 | export type AppDispatch = typeof store.dispatch;
18 |
19 | const { mountStoreToSlice } = beforeMountStore(store);
20 |
21 | export const actions = {
22 | [STORE_NAMES.REMOTE]: mountStoreToSlice(remoteSlice.sliceInstance),
23 | };
24 |
25 | export { mountStoreToSlice, STORE_NAMES };
26 |
27 | export default store;
28 |
--------------------------------------------------------------------------------
/src/store/initImmer.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Immer 兼容低版本浏览器设置
3 | * */
4 |
5 | import { enableAllPlugins } from 'immer';
6 |
7 | enableAllPlugins();
8 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "module": "commonjs",
5 | "jsx": "preserve",
6 | "noEmit": true,
7 | "moduleResolution": "node",
8 | "rootDir": "src",
9 | "noImplicitReturns": true,
10 | "noImplicitThis": true,
11 | "noImplicitAny": true,
12 | "importHelpers": false,
13 | "strictNullChecks": true,
14 | "suppressImplicitAnyIndexErrors": true,
15 | "noUnusedLocals": false,
16 | "useDefineForClassFields": true,
17 | "experimentalDecorators": true,
18 | "baseUrl": "./src",
19 | "incremental": true, // 增量编译,加快速度
20 | "allowUmdGlobalAccess": true,
21 | "downlevelIteration": true,
22 | "paths": {
23 | "store/*": [
24 | "src/store/*"
25 | ]
26 | },
27 | "esModuleInterop": true,
28 | "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
29 | },
30 | "include": [
31 | "typings/**/*",
32 | "src/**/*"
33 | ]
34 | }
35 |
--------------------------------------------------------------------------------
/tsconfig.prod.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "noUnusedLocals": true
5 | },
6 | "include": [
7 | "typings/**/*",
8 | "src/**/*"
9 | ]
10 | }
11 |
--------------------------------------------------------------------------------
/tsconfig.tsbuildinfo:
--------------------------------------------------------------------------------
1 | {"version":"4.3.4"}
--------------------------------------------------------------------------------
/typings/global.d.ts:
--------------------------------------------------------------------------------
1 | import * as lodash from 'lodash';
2 | import * as OriginImmer from 'immer';
3 | import { Draft as ODraft, Immutable as OImmutable } from 'immer';
4 |
5 | // React 已经是全局模块了不需要再引入
6 | declare global {
7 | type _ = typeof lodash;
8 | const immer: typeof OriginImmer;
9 | const __webpack_init_sharing__: any;
10 | const __webpack_share_scopes__: any;
11 | const RUNTIME_NODE_ENV: string;
12 |
13 | interface Window {
14 | __webpack_init_sharing__: any;
15 | __webpack_share_scopes__: any;
16 | __REDUX_DEVTOOLS_EXTENSION_COMPOSE__: Function;
17 | }
18 |
19 | interface Navigator {
20 | userLanguage: string;
21 | }
22 |
23 | namespace Immer {
24 | export type Draft = ODraft;
25 | export type Immutable = OImmutable;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/typings/media.d.ts:
--------------------------------------------------------------------------------
1 | declare module '*.less' {
2 | const content: any;
3 | export default content;
4 | }
5 |
6 | declare module '*.svg' {
7 | const content: string;
8 | export default content;
9 | }
10 |
11 | declare module '*.png' {
12 | const content: string;
13 | export default content;
14 | }
15 | declare module '*.jpg' {
16 | const content: string;
17 | export default content;
18 | }
19 | declare module '*.jpeg' {
20 | const content: string;
21 | export default content;
22 | }
23 | declare module '*.gif' {
24 | const content: string;
25 | export default content;
26 | }
27 | declare module '*.bmp' {
28 | const content: string;
29 | export default content;
30 | }
31 | declare module '*.tiff' {
32 | const content: string;
33 | export default content;
34 | }
35 |
--------------------------------------------------------------------------------