├── app1
├── index.css
├── README.md
├── webpack.config.js
├── package.json
└── index.js
├── app2
├── index.css
├── README.md
├── webpack.config.js
├── app.js
├── package.json
└── index.js
├── app3
├── index.css
├── README.md
├── webpack.config.js
├── app.js
├── package.json
└── index.js
├── base-app
├── public
│ ├── robots.txt
│ ├── favicon.ico
│ ├── logo192.png
│ ├── logo512.png
│ ├── manifest.json
│ └── index.html
├── README.md
├── src
│ ├── App.test.js
│ ├── store
│ │ └── index.js
│ ├── App.js
│ ├── App.css
│ ├── reducers
│ │ └── appReducer.js
│ ├── setupProxy.js
│ ├── components
│ │ ├── Container.jsx
│ │ ├── HelloReact.jsx
│ │ ├── NavBar.jsx
│ │ └── App23Container.jsx
│ ├── index.css
│ ├── index.js
│ ├── serviceWorker.js
│ ├── logo.svg
│ └── helper
│ │ └── system.js
├── .gitignore
└── package.json
├── README.md
└── .gitignore
/app1/index.css:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app2/index.css:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app3/index.css:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/base-app/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 |
--------------------------------------------------------------------------------
/base-app/README.md:
--------------------------------------------------------------------------------
1 | # base-app
2 |
3 | - `npm i` and `npm start`
4 | - open `localhost:3000`
5 |
--------------------------------------------------------------------------------
/base-app/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmad-fajar/demo-micro-fe/HEAD/base-app/public/favicon.ico
--------------------------------------------------------------------------------
/base-app/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmad-fajar/demo-micro-fe/HEAD/base-app/public/logo192.png
--------------------------------------------------------------------------------
/base-app/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmad-fajar/demo-micro-fe/HEAD/base-app/public/logo512.png
--------------------------------------------------------------------------------
/app1/README.md:
--------------------------------------------------------------------------------
1 | # app1
2 |
3 | - `npm i` and `npm start`
4 | - `app1`'s `js` are now served at `http://0.0.0.0:9001/app1.js`
5 |
--------------------------------------------------------------------------------
/app2/README.md:
--------------------------------------------------------------------------------
1 | # app1
2 |
3 | - `npm i` and `npm start`
4 | - `app2`'s `js` are now served at `http://0.0.0.0:9002/app2.js`
5 |
--------------------------------------------------------------------------------
/app3/README.md:
--------------------------------------------------------------------------------
1 | # app1
2 |
3 | - `npm i` and `npm start`
4 | - `app3`'s `js` are now served at `http://0.0.0.0:9003/app3.js`
5 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # demo-micro-fe
2 |
3 | Simple demo for implementing micro-fe with following stacks:
4 | - react
5 | - redux
6 | - webpack
7 | - single-spa
8 |
9 | To run this example, go to each sub folder and `npm start`.
10 | Base app runs at `localhost:3000`.
11 |
--------------------------------------------------------------------------------
/base-app/src/App.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import App from './App';
4 |
5 | it('renders without crashing', () => {
6 | const div = document.createElement('div');
7 | ReactDOM.render(, div);
8 | ReactDOM.unmountComponentAtNode(div);
9 | });
10 |
--------------------------------------------------------------------------------
/base-app/src/store/index.js:
--------------------------------------------------------------------------------
1 | import { combineReducers, createStore } from 'redux';
2 |
3 | import appReducer from '../reducers/appReducer';
4 |
5 | const rootReducer = combineReducers({
6 | appManager: appReducer
7 | });
8 |
9 | const store = createStore(rootReducer);
10 |
11 | export default store;
12 |
--------------------------------------------------------------------------------
/base-app/src/App.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import './App.css';
4 |
5 | import NavBar from './components/NavBar';
6 | import Container from './components/Container';
7 |
8 | function App(props) {
9 | return (
10 |
11 |
12 |
13 |
14 | );
15 | }
16 |
17 | export default App;
18 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | node_modules
5 | .pnp
6 | .pnp.js
7 |
8 | # testing
9 | coverage
10 |
11 | # production
12 | build
13 |
14 | # misc
15 | .DS_Store
16 | .env.local
17 | .env.development.local
18 | .env.test.local
19 | .env.production.local
20 |
21 | npm-debug.log*
22 | yarn-debug.log*
23 | yarn-error.log*
24 |
--------------------------------------------------------------------------------
/base-app/src/App.css:
--------------------------------------------------------------------------------
1 | .App {
2 | text-align: center;
3 | }
4 |
5 | .App-logo {
6 | height: 40vmin;
7 | }
8 |
9 | .App-header {
10 | background-color: #282c34;
11 | min-height: 100vh;
12 | display: flex;
13 | flex-direction: column;
14 | align-items: center;
15 | justify-content: center;
16 | font-size: calc(10px + 2vmin);
17 | color: white;
18 | }
19 |
20 | .App-link {
21 | color: #09d3ac;
22 | }
23 |
--------------------------------------------------------------------------------
/base-app/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # production
12 | /build
13 |
14 | # misc
15 | .DS_Store
16 | .env.local
17 | .env.development.local
18 | .env.test.local
19 | .env.production.local
20 |
21 | npm-debug.log*
22 | yarn-debug.log*
23 | yarn-error.log*
24 |
--------------------------------------------------------------------------------
/base-app/src/reducers/appReducer.js:
--------------------------------------------------------------------------------
1 | const defaultState = {
2 | app2Txt: '',
3 | app3Txt: '',
4 | };
5 |
6 | const appReducer = (s = defaultState, action) => {
7 | const { type, payload: p } = action;
8 | switch(type) {
9 | case 'SAVE_APP2_TXT':
10 | return { ...s, app2Txt: p }
11 |
12 | case 'SAVE_APP3_TXT':
13 | return { ...s, app3Txt: p }
14 |
15 | default:
16 | return s
17 | }
18 | };
19 |
20 | export default appReducer;
21 |
--------------------------------------------------------------------------------
/base-app/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "logo192.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "logo512.png",
17 | "type": "image/png",
18 | "sizes": "512x512"
19 | }
20 | ],
21 | "start_url": ".",
22 | "display": "standalone",
23 | "theme_color": "#000000",
24 | "background_color": "#ffffff"
25 | }
26 |
--------------------------------------------------------------------------------
/base-app/src/setupProxy.js:
--------------------------------------------------------------------------------
1 | const proxy = require('http-proxy-middleware');
2 |
3 | module.exports = app => {
4 | app.use(
5 | '/app1',
6 | proxy({
7 | target: 'http://localhost:9001',
8 | pathRewrite: {
9 | '^/app1': '',
10 | },
11 | }),
12 | );
13 |
14 | app.use(
15 | '/app2',
16 | proxy({
17 | target: 'http://localhost:9002',
18 | pathRewrite: {
19 | '^/app2': '',
20 | },
21 | }),
22 | );
23 |
24 | app.use(
25 | '/app3',
26 | proxy({
27 | target: 'http://localhost:9003',
28 | pathRewrite: {
29 | '^/app3': '',
30 | },
31 | }),
32 | );
33 | };
34 |
--------------------------------------------------------------------------------
/app1/webpack.config.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | // const { CleanWebpackPlugin } = require('clean-webpack-plugin');
3 |
4 | const appName = 'app1';
5 |
6 | module.exports = {
7 | entry : {
8 | [appName]: './index.js',
9 | },
10 | output : {
11 | filename: `${appName}.js`,
12 | path : path.resolve(__dirname , 'build'),
13 | library: appName,
14 | libraryTarget: 'amd',
15 | },
16 | module : {
17 | rules : [
18 | {test : /\.(js)$/, use:'babel-loader'},
19 | {test : /\.css$/, use:['style-loader', 'css-loader']},
20 | ]
21 | },
22 | mode:'development',
23 | plugins : [
24 | // new CleanWebpackPlugin(),
25 | ],
26 | }
27 |
--------------------------------------------------------------------------------
/app2/webpack.config.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | // const { CleanWebpackPlugin } = require('clean-webpack-plugin');
3 |
4 | const appName = 'app2';
5 |
6 | module.exports = {
7 | entry : {
8 | [appName]: './index.js',
9 | },
10 | output : {
11 | filename: `${appName}.js`,
12 | path : path.resolve(__dirname , 'build'),
13 | library: appName,
14 | libraryTarget: 'amd',
15 | },
16 | module : {
17 | rules : [
18 | {test : /\.(js)$/, use:'babel-loader'},
19 | {test : /\.css$/, use:['style-loader', 'css-loader']},
20 | ]
21 | },
22 | mode:'development',
23 | plugins : [
24 | // new CleanWebpackPlugin(),
25 | ],
26 | }
27 |
--------------------------------------------------------------------------------
/app3/webpack.config.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | // const { CleanWebpackPlugin } = require('clean-webpack-plugin');
3 |
4 | const appName = 'app3';
5 |
6 | module.exports = {
7 | entry : {
8 | [appName]: './index.js',
9 | },
10 | output : {
11 | filename: `${appName}.js`,
12 | path : path.resolve(__dirname , 'build'),
13 | library: appName,
14 | libraryTarget: 'amd',
15 | },
16 | module : {
17 | rules : [
18 | {test : /\.(js)$/, use:'babel-loader'},
19 | {test : /\.css$/, use:['style-loader', 'css-loader']},
20 | ]
21 | },
22 | mode:'development',
23 | plugins : [
24 | // new CleanWebpackPlugin(),
25 | ],
26 | }
27 |
--------------------------------------------------------------------------------
/base-app/src/components/Container.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Route, Switch } from 'react-router-dom';
3 |
4 | import App23Container from './App23Container';
5 | import HelloReact from './HelloReact';
6 |
7 | function Container(props) {
8 | return (
9 |
10 |
11 |
12 | }
16 | />
17 |
18 | }
22 | />
23 |
24 |
25 |
26 | );
27 | };
28 |
29 | export default Container;
30 |
--------------------------------------------------------------------------------
/base-app/src/components/HelloReact.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import logo from '../logo.svg';
4 |
5 | const HelloReact = () => {
6 | return (
7 |
23 | );
24 | };
25 |
26 | export default HelloReact;
27 |
--------------------------------------------------------------------------------
/app2/app.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { connect } from 'react-redux';
3 |
4 | const App = p => {
5 | return (
6 |
7 | Hello App2 World
8 |
9 |
10 |
11 | Message from app3: {p.txt3}
12 |
13 |
14 |
p.saveTxt2(v.currentTarget.value)}
17 | />
18 |
19 | );
20 | };
21 |
22 | const mapState = s => {
23 | return {
24 | txt3: s.appManager.app3Txt,
25 | };
26 | };
27 |
28 | const mapDispatch = d => {
29 | return {
30 |
31 | saveTxt2: s => d(function () {
32 | return { type: 'SAVE_APP2_TXT', payload: s };
33 | }()),
34 |
35 | };
36 | };
37 |
38 | export default connect(mapState, mapDispatch)(App);
39 |
--------------------------------------------------------------------------------
/app3/app.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { connect } from 'react-redux';
3 |
4 | const App = p => {
5 | return (
6 |
7 | Hello App3 World
8 |
9 |
10 |
11 | Message from app2: {p.txt2}
12 |
13 |
14 |
p.saveTxt3(v.currentTarget.value)}
17 | />
18 |
19 | );
20 | };
21 |
22 | const mapStateToProps = s => {
23 | return {
24 | txt2: s.appManager.app2Txt,
25 | };
26 | };
27 |
28 | const mapDispatchToProps = d => {
29 | return {
30 |
31 | saveTxt3: s => d(function () {
32 | return { type: 'SAVE_APP3_TXT', payload: s };
33 | }()),
34 |
35 | };
36 | };
37 |
38 | export default connect(mapStateToProps, mapDispatchToProps)(App);
39 |
--------------------------------------------------------------------------------
/base-app/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "base-app",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "http-proxy-middleware": "^0.20.0",
7 | "react": "^16.9.0",
8 | "react-dom": "^16.9.0",
9 | "react-redux": "^7.1.1",
10 | "react-router-dom": "^5.0.1",
11 | "react-scripts": "3.1.2",
12 | "redux": "^4.0.4",
13 | "single-spa": "^4.4.1",
14 | "single-spa-react": "^2.10.2"
15 | },
16 | "scripts": {
17 | "start": "react-scripts start",
18 | "build": "react-scripts build",
19 | "test": "react-scripts test",
20 | "eject": "react-scripts eject"
21 | },
22 | "eslintConfig": {
23 | "extends": "react-app"
24 | },
25 | "browserslist": {
26 | "production": [
27 | ">0.2%",
28 | "not dead",
29 | "not op_mini all"
30 | ],
31 | "development": [
32 | "last 1 chrome version",
33 | "last 1 firefox version",
34 | "last 1 safari version"
35 | ]
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/base-app/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
4 | "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
5 | sans-serif;
6 | -webkit-font-smoothing: antialiased;
7 | -moz-osx-font-smoothing: grayscale;
8 | }
9 |
10 | code {
11 | font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
12 | monospace;
13 | }
14 |
15 | #ex2-container {
16 | font-size: 32px;
17 | font-weight: normal;
18 | }
19 |
20 | #ex2-container p span {
21 | font-weight: bold;
22 | }
23 |
24 | #example2-header p {
25 | margin-bottom: 0;
26 | margin-top: 0;
27 | }
28 |
29 | #container23 {
30 | display: flex;
31 | height: 10em;
32 | }
33 |
34 | #container23 > div {
35 | border: 1px solid grey;
36 | box-sizing: border-box;
37 | width: 50%;
38 | }
39 |
40 | #container23 input {
41 | border-radius: 4px;
42 | height: 1.5em;
43 | }
44 |
45 | #container23 p {
46 | color: red;
47 | }
48 |
--------------------------------------------------------------------------------
/app1/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "app1",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "start": "NODE_ENV=development webpack-dev-server --port 9001 --host 0.0.0.0 --content-base build/"
9 | },
10 | "author": "",
11 | "license": "ISC",
12 | "dependencies": {
13 | "react": "^16.9.0",
14 | "react-dom": "^16.9.0",
15 | "single-spa-react": "^2.10.2"
16 | },
17 | "devDependencies": {
18 | "@babel/core": "^7.6.0",
19 | "@babel/preset-env": "^7.6.0",
20 | "@babel/preset-react": "^7.0.0",
21 | "babel-loader": "^8.0.6",
22 | "css-loader": "^3.2.0",
23 | "html-webpack-plugin": "^3.2.0",
24 | "style-loader": "^1.0.0",
25 | "webpack": "^4.40.2",
26 | "webpack-cli": "^3.3.9",
27 | "webpack-dev-server": "^3.8.1"
28 | },
29 | "babel": {
30 | "presets": [
31 | "@babel/preset-env",
32 | "@babel/preset-react"
33 | ]
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/app2/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "app1",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "start": "NODE_ENV=development webpack-dev-server --port 9002 --host 0.0.0.0 --content-base build/"
9 | },
10 | "author": "",
11 | "license": "ISC",
12 | "dependencies": {
13 | "react": "^16.9.0",
14 | "react-dom": "^16.9.0",
15 | "react-redux": "^7.1.1",
16 | "redux": "^4.0.4",
17 | "single-spa-react": "^2.10.2"
18 | },
19 | "devDependencies": {
20 | "@babel/core": "^7.6.0",
21 | "@babel/preset-env": "^7.6.0",
22 | "@babel/preset-react": "^7.0.0",
23 | "babel-loader": "^8.0.6",
24 | "css-loader": "^3.2.0",
25 | "html-webpack-plugin": "^3.2.0",
26 | "style-loader": "^1.0.0",
27 | "webpack": "^4.40.2",
28 | "webpack-cli": "^3.3.9",
29 | "webpack-dev-server": "^3.8.1"
30 | },
31 | "babel": {
32 | "presets": [
33 | "@babel/preset-env",
34 | "@babel/preset-react"
35 | ]
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/app3/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "app1",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "start": "NODE_ENV=development webpack-dev-server --port 9003 --host 0.0.0.0 --content-base build/"
9 | },
10 | "author": "",
11 | "license": "ISC",
12 | "dependencies": {
13 | "react": "^16.9.0",
14 | "react-dom": "^16.9.0",
15 | "react-redux": "^7.1.1",
16 | "redux": "^4.0.4",
17 | "single-spa-react": "^2.10.2"
18 | },
19 | "devDependencies": {
20 | "@babel/core": "^7.6.0",
21 | "@babel/preset-env": "^7.6.0",
22 | "@babel/preset-react": "^7.0.0",
23 | "babel-loader": "^8.0.6",
24 | "css-loader": "^3.2.0",
25 | "html-webpack-plugin": "^3.2.0",
26 | "style-loader": "^1.0.0",
27 | "webpack": "^4.40.2",
28 | "webpack-cli": "^3.3.9",
29 | "webpack-dev-server": "^3.8.1"
30 | },
31 | "babel": {
32 | "presets": [
33 | "@babel/preset-env",
34 | "@babel/preset-react"
35 | ]
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/base-app/src/components/NavBar.jsx:
--------------------------------------------------------------------------------
1 | import React, { useState } from 'react'
2 |
3 | const SideBar = p => {
4 | const [activeItem, setActive] = useState('home');
5 |
6 | const clickHandler = n => {
7 | setActive(n);
8 | p.history.push(`/${n}`);
9 | };
10 |
11 | const navItem = (label, name) => {
12 | let cName = 'nav-item';
13 | if (activeItem === name) { cName += ' active'; }
14 |
15 | return (
16 | clickHandler(name)} >
17 | {label}
18 |
19 | );
20 | };
21 |
22 | return (
23 |
24 |
34 |
35 | );
36 | };
37 |
38 | export default SideBar;
39 |
--------------------------------------------------------------------------------
/base-app/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import './index.css';
4 | import App from './App';
5 | import * as serviceWorker from './serviceWorker';
6 |
7 | import { registerApplication, start } from 'single-spa';
8 |
9 | import { Provider } from 'react-redux';
10 | import store from './store';
11 |
12 | // import SystemJS
13 | import './helper/system';
14 |
15 | import { BrowserRouter, Route } from 'react-router-dom';
16 |
17 |
18 | function startApp() {
19 | registerApplication(
20 | 'app1',
21 |
22 | async () => await window.SystemJS.import('/app1/app1.js'),
23 |
24 | (location) => location.pathname.startsWith('/ex1'),
25 |
26 | { sampleProp: 'just some random string' },
27 | );
28 |
29 | start();
30 | }
31 | startApp();
32 |
33 | ReactDOM.render(
34 | (
35 |
36 |
37 |
38 |
39 |
40 | ),
41 | document.getElementById('root')
42 | );
43 |
44 | // If you want your app to work offline and load faster, you can change
45 | // unregister() to register() below. Note this comes with some pitfalls.
46 | // Learn more about service workers: https://bit.ly/CRA-PWA
47 | serviceWorker.unregister();
48 |
--------------------------------------------------------------------------------
/app1/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import singleSpaReact from 'single-spa-react';
4 | import './index.css';
5 |
6 | const AppRoot = p => {
7 | console.log('props: ', p)
8 | const s = {
9 | color: 'blue',
10 | fontSize: '48px',
11 | fontWeight: 'bold',
12 | };
13 | return(
14 |
15 | Hello App1 World
16 |
17 | )
18 | };
19 |
20 | // ReactDOM.render(, document.getElementById('app'));
21 |
22 | const reactLifeCycles = singleSpaReact({
23 | React,
24 | ReactDOM,
25 | domElementGetter,
26 | rootComponent: AppRoot,
27 | suppressComponentDidCatchWarning: true,
28 | });
29 |
30 | export const bootstrap = [reactLifeCycles.bootstrap];
31 | export const mount = [reactLifeCycles.mount];
32 | export const unmount = [reactLifeCycles.unmount];
33 |
34 | function domElementGetter() {
35 | const APP_NAME = 'app1';
36 | const MOUNT_DIV = 'app';
37 |
38 | let el = document.getElementById(APP_NAME);
39 |
40 | if (!el) {
41 | el = document.createElement('div');
42 | el.id = APP_NAME;
43 | }
44 |
45 | let app = document.getElementById(MOUNT_DIV);
46 | if (!app) {
47 | app = app.createElement('div');
48 | app.id = MOUNT_DIV;
49 | document.body.appendChild(app);
50 | }
51 |
52 | app.appendChild(el);
53 |
54 | return el;
55 | }
56 |
--------------------------------------------------------------------------------
/base-app/src/components/App23Container.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { registerApplication, start } from 'single-spa';
3 | import { connect } from 'react-redux';
4 |
5 | import store from '../store';
6 |
7 | let hasRegister = false;
8 |
9 | const App23Container = p => {
10 | const apps = [
11 | {
12 | name: 'app2',
13 | js: '/app2/app2.js',
14 | props: {
15 | store,
16 | },
17 | },
18 | {
19 | name: 'app3',
20 | js: '/app3/app3.js',
21 | props: {
22 | store,
23 | },
24 | },
25 | ];
26 |
27 | async function startApp() {
28 | await apps.forEach(a => {
29 | registerApplication(
30 | a.name,
31 |
32 | async () => await window.SystemJS.import(a.js),
33 |
34 | location => location.pathname.startsWith('/ex2'),
35 |
36 | { ...a.props },
37 | );
38 | });
39 |
40 | start();
41 | return;
42 | }
43 |
44 | if(!hasRegister) {
45 | startApp();
46 | hasRegister = true;
47 | }
48 |
49 | return (
50 |
62 | );
63 | };
64 |
65 | const mapState = s => {
66 | const { appManager: a } = s;
67 | return {
68 | app2Txt: a.app2Txt,
69 | app3Txt: a.app3Txt,
70 | };
71 | }
72 |
73 | export default connect(mapState)(App23Container);
74 |
--------------------------------------------------------------------------------
/app2/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import { Provider } from 'react-redux';
4 | import singleSpaReact from 'single-spa-react';
5 |
6 | import App from './app';
7 |
8 | import './index.css';
9 |
10 | const AppRoot = p => {
11 | return (
12 |
13 |
14 |
15 | );
16 | };
17 |
18 | // ReactDOM.render(, document.getElementById('container2'));
19 |
20 | const reactLifeCycles = singleSpaReact({
21 | React,
22 | ReactDOM,
23 | domElementGetter,
24 | rootComponent: AppRoot,
25 | suppressComponentDidCatchWarning: true,
26 | });
27 |
28 | export const bootstrap = [reactLifeCycles.bootstrap];
29 | export const mount = [reactLifeCycles.mount];
30 | export const unmount = [reactLifeCycles.unmount];
31 |
32 | function domElementGetter() {
33 | const APP_NAME = 'app2';
34 | const MOUNT_DIV = 'container2';
35 | const APPS_CONTAINER_DIV = 'container23';
36 | const EX2_CONTAINER_DIV = 'ex2-container';
37 |
38 | let app = document.getElementById('app');
39 | if (!app) {
40 | app = document.createElement('div');
41 | app.id = 'app';
42 | document.body.appendChild(app);
43 | }
44 |
45 | let ex2ContainerDiv = document.getElementById(EX2_CONTAINER_DIV);
46 | if (!ex2ContainerDiv) {
47 | ex2ContainerDiv = document.createElement('div');
48 | ex2ContainerDiv.id = EX2_CONTAINER_DIV;
49 | app.appendChild(ex2ContainerDiv);
50 | }
51 |
52 | let appsContainerDiv = document.getElementById(APPS_CONTAINER_DIV);
53 | if (!appsContainerDiv) {
54 | appsContainerDiv = document.createElement('div');
55 | appsContainerDiv.id = APPS_CONTAINER_DIV;
56 | ex2ContainerDiv.appendChild(appsContainerDiv);
57 | }
58 |
59 | let mountDiv = document.getElementById(MOUNT_DIV);
60 | if (!mountDiv) {
61 | mountDiv = document.createElement('div');
62 | mountDiv.id = MOUNT_DIV;
63 | appsContainerDiv.appendChild(mountDiv);
64 | }
65 |
66 | let el = document.getElementById(APP_NAME);
67 | if (!el) {
68 | el = document.createElement('div');
69 | el.id = APP_NAME;
70 | }
71 |
72 | mountDiv.appendChild(el);
73 |
74 | return el;
75 | }
76 |
--------------------------------------------------------------------------------
/app3/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import { Provider } from 'react-redux';
4 | import singleSpaReact from 'single-spa-react';
5 |
6 | import App from './app';
7 |
8 | import './index.css';
9 |
10 | const AppRoot = p => {
11 | return (
12 |
13 |
14 |
15 | );
16 | };
17 |
18 | // ReactDOM.render(, document.getElementById('container3'));
19 |
20 | const reactLifeCycles = singleSpaReact({
21 | React,
22 | ReactDOM,
23 | domElementGetter,
24 | rootComponent: AppRoot,
25 | suppressComponentDidCatchWarning: true,
26 | });
27 |
28 | export const bootstrap = [reactLifeCycles.bootstrap];
29 | export const mount = [reactLifeCycles.mount];
30 | export const unmount = [reactLifeCycles.unmount];
31 |
32 | function domElementGetter() {
33 | const APP_NAME = 'app3';
34 | const MOUNT_DIV = 'container3';
35 | const APPS_CONTAINER_DIV = 'container23';
36 | const EX2_CONTAINER_DIV = 'ex2-container';
37 |
38 | let app = document.getElementById('app');
39 | if (!app) {
40 | app = document.createElement('div');
41 | app.id = 'app';
42 | document.body.appendChild(app);
43 | }
44 |
45 | let ex2ContainerDiv = document.getElementById(EX2_CONTAINER_DIV);
46 | if (!ex2ContainerDiv) {
47 | ex2ContainerDiv = document.createElement('div');
48 | ex2ContainerDiv.id = EX2_CONTAINER_DIV;
49 | app.appendChild(ex2ContainerDiv);
50 | }
51 |
52 | let appsContainerDiv = document.getElementById(APPS_CONTAINER_DIV);
53 | if (!appsContainerDiv) {
54 | appsContainerDiv = document.createElement('div');
55 | appsContainerDiv.id = APPS_CONTAINER_DIV;
56 | ex2ContainerDiv.appendChild(appsContainerDiv);
57 | }
58 |
59 | let mountDiv = document.getElementById(MOUNT_DIV);
60 | if (!mountDiv) {
61 | mountDiv = document.createElement('div');
62 | mountDiv.id = MOUNT_DIV;
63 | appsContainerDiv.appendChild(mountDiv);
64 | }
65 |
66 | let el = document.getElementById(APP_NAME);
67 | if (!el) {
68 | el = document.createElement('div');
69 | el.id = APP_NAME;
70 | }
71 |
72 | mountDiv.appendChild(el);
73 |
74 | return el;
75 | }
76 |
--------------------------------------------------------------------------------
/base-app/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
12 |
13 |
17 |
18 |
27 | React App
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/base-app/src/serviceWorker.js:
--------------------------------------------------------------------------------
1 | // This optional code is used to register a service worker.
2 | // register() is not called by default.
3 |
4 | // This lets the app load faster on subsequent visits in production, and gives
5 | // it offline capabilities. However, it also means that developers (and users)
6 | // will only see deployed updates on subsequent visits to a page, after all the
7 | // existing tabs open on the page have been closed, since previously cached
8 | // resources are updated in the background.
9 |
10 | // To learn more about the benefits of this model and instructions on how to
11 | // opt-in, read https://bit.ly/CRA-PWA
12 |
13 | const isLocalhost = Boolean(
14 | window.location.hostname === 'localhost' ||
15 | // [::1] is the IPv6 localhost address.
16 | window.location.hostname === '[::1]' ||
17 | // 127.0.0.1/8 is considered localhost for IPv4.
18 | window.location.hostname.match(
19 | /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
20 | )
21 | );
22 |
23 | export function register(config) {
24 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
25 | // The URL constructor is available in all browsers that support SW.
26 | const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);
27 | if (publicUrl.origin !== window.location.origin) {
28 | // Our service worker won't work if PUBLIC_URL is on a different origin
29 | // from what our page is served on. This might happen if a CDN is used to
30 | // serve assets; see https://github.com/facebook/create-react-app/issues/2374
31 | return;
32 | }
33 |
34 | window.addEventListener('load', () => {
35 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
36 |
37 | if (isLocalhost) {
38 | // This is running on localhost. Let's check if a service worker still exists or not.
39 | checkValidServiceWorker(swUrl, config);
40 |
41 | // Add some additional logging to localhost, pointing developers to the
42 | // service worker/PWA documentation.
43 | navigator.serviceWorker.ready.then(() => {
44 | console.log(
45 | 'This web app is being served cache-first by a service ' +
46 | 'worker. To learn more, visit https://bit.ly/CRA-PWA'
47 | );
48 | });
49 | } else {
50 | // Is not localhost. Just register service worker
51 | registerValidSW(swUrl, config);
52 | }
53 | });
54 | }
55 | }
56 |
57 | function registerValidSW(swUrl, config) {
58 | navigator.serviceWorker
59 | .register(swUrl)
60 | .then(registration => {
61 | registration.onupdatefound = () => {
62 | const installingWorker = registration.installing;
63 | if (installingWorker == null) {
64 | return;
65 | }
66 | installingWorker.onstatechange = () => {
67 | if (installingWorker.state === 'installed') {
68 | if (navigator.serviceWorker.controller) {
69 | // At this point, the updated precached content has been fetched,
70 | // but the previous service worker will still serve the older
71 | // content until all client tabs are closed.
72 | console.log(
73 | 'New content is available and will be used when all ' +
74 | 'tabs for this page are closed. See https://bit.ly/CRA-PWA.'
75 | );
76 |
77 | // Execute callback
78 | if (config && config.onUpdate) {
79 | config.onUpdate(registration);
80 | }
81 | } else {
82 | // At this point, everything has been precached.
83 | // It's the perfect time to display a
84 | // "Content is cached for offline use." message.
85 | console.log('Content is cached for offline use.');
86 |
87 | // Execute callback
88 | if (config && config.onSuccess) {
89 | config.onSuccess(registration);
90 | }
91 | }
92 | }
93 | };
94 | };
95 | })
96 | .catch(error => {
97 | console.error('Error during service worker registration:', error);
98 | });
99 | }
100 |
101 | function checkValidServiceWorker(swUrl, config) {
102 | // Check if the service worker can be found. If it can't reload the page.
103 | fetch(swUrl)
104 | .then(response => {
105 | // Ensure service worker exists, and that we really are getting a JS file.
106 | const contentType = response.headers.get('content-type');
107 | if (
108 | response.status === 404 ||
109 | (contentType != null && contentType.indexOf('javascript') === -1)
110 | ) {
111 | // No service worker found. Probably a different app. Reload the page.
112 | navigator.serviceWorker.ready.then(registration => {
113 | registration.unregister().then(() => {
114 | window.location.reload();
115 | });
116 | });
117 | } else {
118 | // Service worker found. Proceed as normal.
119 | registerValidSW(swUrl, config);
120 | }
121 | })
122 | .catch(() => {
123 | console.log(
124 | 'No internet connection found. App is running in offline mode.'
125 | );
126 | });
127 | }
128 |
129 | export function unregister() {
130 | if ('serviceWorker' in navigator) {
131 | navigator.serviceWorker.ready.then(registration => {
132 | registration.unregister();
133 | });
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/base-app/src/logo.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/base-app/src/helper/system.js:
--------------------------------------------------------------------------------
1 | /*
2 | * SystemJS v0.20.19 Dev
3 | */
4 | // eslint-disable-next-line
5 | !function(){"use strict";function e(e){return ut?Symbol():"@@"+e}function t(e,t){ot||(t=t.replace(at?/file:\/\/\//g:/file:\/\//g,""));var r,n=(e.message||e)+"\n "+t;r=ft&&e.fileName?new Error(n,e.fileName,e.lineNumber):new Error(n);var o=e.originalErr?e.originalErr.stack:e.stack;return r.stack=it?n+"\n "+o:o,r.originalErr=e.originalErr||e,r}function r(e,t){throw new RangeError('Unable to resolve "'+e+'" to '+t)}function n(e,t){e=e.trim();var n=t&&t.substr(0,t.indexOf(":")+1),o=e[0],i=e[1];if("/"===o&&"/"===i)return n||r(e,t),n+e;if("."===o&&("/"===i||"."===i&&("/"===e[2]||2===e.length&&(e+="/"))||1===e.length&&(e+="/"))||"/"===o){var a,s=!n||"/"!==t[n.length];if(s?(void 0===t&&r(e,t),a=t):a="/"===t[n.length+1]?"file:"!==n?(a=t.substr(n.length+2)).substr(a.indexOf("/")+1):t.substr(8):t.substr(n.length+1),"/"===o){if(!s)return t.substr(0,t.length-a.length-1)+e;r(e,t)}for(var u=a.substr(0,a.lastIndexOf("/")+1)+e,l=[],c=-1,f=0;f1&&g(e,r,i))})).then(function(t){if(void 0!==t){if(!(t instanceof l))throw new TypeError("Instantiate did not return a valid Module object.");return delete i.records[r.key],e.trace&&v(e,r,n),o[r.key]=t}var a=r.registration;if(r.registration=void 0,!a)throw new TypeError("Module instantiation did not call an anonymous or correctly named System.register.");return n.dependencies=a[0],r.importerSetters=[],n.moduleObj={},a[2]?(n.moduleObj.default=n.moduleObj.__useDefault={},n.executingRequire=a[1],n.execute=a[2]):y(e,r,n,a[1]),r}).catch(function(e){throw r.linkRecord=void 0,r.loadError=r.loadError||t(e,"Instantiating "+r.key)}))}function m(e,t,r,n,o,i){return e.resolve(t,r).then(function(r){i&&(i[t]=r);var a=o.records[r],s=n[r];if(s&&(!a||a.module&&s!==a.module))return s;if(a&&a.loadError)throw a.loadError;(!a||!s&&a.module)&&(a=d(o,r,a&&a.registration));var u=a.linkRecord;return u?h(e,a,u,n,o):a})}function v(e,t,r){e.loads=e.loads||{},e.loads[t.key]={key:t.key,deps:r.dependencies,dynamicDeps:[],depMap:r.depMap||{}}}function y(e,t,r,n){var o=r.moduleObj,i=t.importerSetters,a=!1,s=n.call(st,function(e,t){if("object"==typeof e){var r=!1;for(var n in e)t=e[n],"__useDefault"===n||n in o&&o[n]===t||(r=!0,o[n]=t);if(!1===r)return t}else{if((a||e in o)&&o[e]===t)return t;o[e]=t}for(var s=0;sthis.len&&(this.match=e,this.len=r)}}function N(e,t){if(Object.hasOwnProperty.call(e,t))return t;var r={name:t,match:void 0,len:0};return Object.keys(e).forEach(z,r),r.match}function J(e,t,r,n){if("file:///"===e.substr(0,8)){if(Ft)return $(e,t,r,n);throw new Error("Unable to fetch file URLs in this environment.")}e=e.replace(/#/g,"%23");var o={headers:{Accept:"application/x-es-module, */*"}};return r&&(o.integrity=r),t&&("string"==typeof t&&(o.headers.Authorization=t),o.credentials="include"),fetch(e,o).then(function(e){if(e.ok)return n?e.arrayBuffer():e.text();throw new Error("Fetch error: "+e.status+" "+e.statusText)})}function $(e,t,r,n){return new Promise(function(r,o){function i(){r(n?s.response:s.responseText)}function a(){o(new Error("XHR error: "+(s.status?" ("+s.status+(s.statusText?" "+s.statusText:"")+")":"")+" loading "+e))}e=e.replace(/#/g,"%23");var s=new XMLHttpRequest;n&&(s.responseType="arraybuffer"),s.onreadystatechange=function(){4===s.readyState&&(0==s.status?s.response?i():(s.addEventListener("error",a),s.addEventListener("load",i)):200===s.status?i():a())},s.open("GET",e,!0),s.setRequestHeader&&(s.setRequestHeader("Accept","application/x-es-module, */*"),t&&("string"==typeof t&&s.setRequestHeader("Authorization",t),s.withCredentials=!0)),s.send(null)})}function B(e,t,r,n){return"file:///"!=e.substr(0,8)?Promise.reject(new Error('Unable to fetch "'+e+'". Only file URLs of the form file:/// supported running in Node.')):(Lt=Lt||require("fs"),e=at?e.replace(/\//g,"\\").substr(8):e.substr(7),new Promise(function(t,r){Lt.readFile(e,function(e,o){if(e)return r(e);if(n)t(o);else{var i=o+"";"\ufeff"===i[0]&&(i=i.substr(1)),t(i)}})}))}function W(){throw new Error("No fetch method is defined for this environment.")}function G(){return{pluginKey:void 0,pluginArgument:void 0,pluginModule:void 0,packageKey:void 0,packageConfig:void 0,load:void 0}}function H(e,t,r){var n=G();if(r){var o;t.pluginFirst?-1!==(o=r.lastIndexOf("!"))&&(n.pluginArgument=n.pluginKey=r.substr(0,o)):-1!==(o=r.indexOf("!"))&&(n.pluginArgument=n.pluginKey=r.substr(o+1)),n.packageKey=N(t.packages,r),n.packageKey&&(n.packageConfig=t.packages[n.packageKey])}return n}function Z(e,t){var r=this[St],n=G(),o=H(this,r,t),i=this;return Promise.resolve().then(function(){var r=e.lastIndexOf("#?");if(-1===r)return Promise.resolve(e);var n=he.call(i,e.substr(r+2));return me.call(i,n,t,!0).then(function(t){return t?e.substr(0,r):"@empty"})}).then(function(e){var a=ne(r.pluginFirst,e);return a?(n.pluginKey=a.plugin,Promise.all([ee.call(i,r,a.argument,o&&o.pluginArgument||t,n,o,!0),i.resolve(a.plugin,t)]).then(function(e){if(n.pluginArgument=e[0],n.pluginKey=e[1],n.pluginArgument===n.pluginKey)throw new Error("Plugin "+n.pluginArgument+" cannot load itself, make sure it is excluded from any wildcard meta configuration via a custom loader: false rule.");return oe(r.pluginFirst,e[0],e[1])})):ee.call(i,r,e,o&&o.pluginArgument||t,n,o,!1)}).then(function(e){return ve.call(i,e,t,o)}).then(function(e){return re.call(i,r,e,n),n.pluginKey||!n.load.loader?e:i.resolve(n.load.loader,e).then(function(t){return n.pluginKey=t,n.pluginArgument=e,e})}).then(function(e){return i[jt][e]=n,e})}function X(e,t){var r=ne(e.pluginFirst,t);if(r){var n=X.call(this,e,r.plugin);return oe(e.pluginFirst,Q.call(this,e,r.argument,void 0,!1,!1),n)}return Q.call(this,e,t,void 0,!1,!1)}function Y(e,t){var r=this[St],n=G(),o=o||H(this,r,t),i=ne(r.pluginFirst,e);return i?(n.pluginKey=Y.call(this,i.plugin,t),oe(r.pluginFirst,V.call(this,r,i.argument,o.pluginArgument||t,n,o,!!n.pluginKey),n.pluginKey)):V.call(this,r,e,o.pluginArgument||t,n,o,!!n.pluginKey)}function Q(e,t,r,o,i){var a=n(t,r||nt);if(a)return T(e.baseURL,e.paths,a);if(o){var s=N(e.map,t);if(s&&(t=e.map[s]+t.substr(s.length),a=n(t,nt)))return T(e.baseURL,e.paths,a)}if(this.registry.has(t))return t;if("@node/"===t.substr(0,6))return t;var u=i&&"/"!==t[t.length-1],l=T(e.baseURL,e.paths,u?t+"/":t);return u?l.substr(0,l.length-1):l}function V(e,t,r,n,o,i){if(o&&o.packageConfig&&"."!==t[0]){var a=o.packageConfig.map,s=a&&N(a,t);if(s&&"string"==typeof a[s]){var u=ue(this,e,o.packageConfig,o.packageKey,s,t,n,i);if(u)return u}}var l=Q.call(this,e,t,r,!0,!0),c=de(e,l);if(n.packageKey=c&&c.packageKey||N(e.packages,l),!n.packageKey)return l;if(-1!==e.packageConfigKeys.indexOf(l))return n.packageKey=void 0,l;n.packageConfig=e.packages[n.packageKey]||(e.packages[n.packageKey]=Ee());var f=l.substr(n.packageKey.length+1);return ae(this,e,n.packageConfig,n.packageKey,f,n,i)}function ee(e,t,r,n,o,i){var a=this;return Et.then(function(){if(o&&o.packageConfig&&"./"!==t.substr(0,2)){var r=o.packageConfig.map,s=r&&N(r,t);if(s)return ce(a,e,o.packageConfig,o.packageKey,s,t,n,i)}return Et}).then(function(o){if(o)return o;var s=Q.call(a,e,t,r,!0,!0),u=de(e,s);return n.packageKey=u&&u.packageKey||N(e.packages,s),n.packageKey?-1!==e.packageConfigKeys.indexOf(s)?(n.packageKey=void 0,n.load=te(),n.load.format="json",n.load.loader="",Promise.resolve(s)):(n.packageConfig=e.packages[n.packageKey]||(e.packages[n.packageKey]=Ee()),(u&&!n.packageConfig.configured?pe(a,e,u.configPath,n):Et).then(function(){var t=s.substr(n.packageKey.length+1);return le(a,e,n.packageConfig,n.packageKey,t,n,i)})):Promise.resolve(s)})}function te(){return{extension:"",deps:void 0,format:void 0,loader:void 0,scriptLoad:void 0,globals:void 0,nonce:void 0,integrity:void 0,sourceMap:void 0,exports:void 0,encapsulateGlobal:!1,crossOrigin:void 0,cjsRequireDetection:!0,cjsDeferDepsExecute:!1,esModule:!1}}function re(e,t,r){r.load=r.load||te();var n,o=0;for(var i in e.meta)if(-1!==(n=i.indexOf("*"))&&i.substr(0,n)===t.substr(0,n)&&i.substr(n+1)===t.substr(t.length-i.length+n+1)){var a=i.split("/").length;a>o&&(o=a),F(r.load,e.meta[i],o!==a)}if(e.meta[t]&&F(r.load,e.meta[t],!1),r.packageKey){var s=t.substr(r.packageKey.length+1),u={};if(r.packageConfig.meta){o=0;ge(r.packageConfig.meta,s,function(e,t,r){r>o&&(o=r),F(u,t,r&&o>r)}),F(r.load,u,!1)}!r.packageConfig.format||r.pluginKey||r.load.loader||(r.load.format=r.load.format||r.packageConfig.format)}}function ne(e,t){var r,n,o=e?t.indexOf("!"):t.lastIndexOf("!");if(-1!==o)return e?(r=t.substr(o+1),n=t.substr(0,o)):(r=t.substr(0,o),n=t.substr(o+1)||r.substr(r.lastIndexOf(".")+1)),{argument:r,plugin:n}}function oe(e,t,r){return e?r+"!"+t:t+"!"+r}function ie(e,t,r,n,o){if(!n||!t.defaultExtension||"/"===n[n.length-1]||o)return n;var i=!1;if(t.meta&&ge(t.meta,n,function(e,t,r){if(0===r||e.lastIndexOf("*")!==e.length-1)return i=!0}),!i&&e.meta&&ge(e.meta,r+"/"+n,function(e,t,r){if(0===r||e.lastIndexOf("*")!==e.length-1)return i=!0}),i)return n;var a="."+t.defaultExtension;return n.substr(n.length-a.length)!==a?n+a:n}function ae(e,t,r,n,o,i,a){if(!o){if(!r.main)return n;o="./"===r.main.substr(0,2)?r.main.substr(2):r.main}if(r.map){var s="./"+o,u=N(r.map,s);if(u||(s="./"+ie(t,r,n,o,a))!=="./"+o&&(u=N(r.map,s)),u){var l=ue(e,t,r,n,u,s,i,a);if(l)return l}}return n+"/"+ie(t,r,n,o,a)}function se(e,t,r){return!(t.substr(0,e.length)===e&&r.length>e.length)}function ue(e,t,r,n,o,i,a,s){"/"===i[i.length-1]&&(i=i.substr(0,i.length-1));var u=r.map[o];if("object"==typeof u)throw new Error("Synchronous conditional normalization not supported sync normalizing "+o+" in "+n);if(se(o,u,i)&&"string"==typeof u)return V.call(e,t,u+i.substr(o.length),n+"/",a,a,s)}function le(e,t,r,n,o,i,a){if(!o){if(!r.main)return Promise.resolve(n);o="./"===r.main.substr(0,2)?r.main.substr(2):r.main}var s,u;return r.map&&(s="./"+o,(u=N(r.map,s))||(s="./"+ie(t,r,n,o,a))!=="./"+o&&(u=N(r.map,s))),(u?ce(e,t,r,n,u,s,i,a):Et).then(function(e){return e?Promise.resolve(e):Promise.resolve(n+"/"+ie(t,r,n,o,a))})}function ce(e,t,r,n,o,i,a,s){"/"===i[i.length-1]&&(i=i.substr(0,i.length-1));var u=r.map[o];if("string"==typeof u)return se(o,u,i)?ee.call(e,t,u+i.substr(o.length),n+"/",a,a,s).then(function(t){return ve.call(e,t,n+"/",a)}):Et;var l=[],c=[];for(var d in u){var p=he(d);c.push({condition:p,map:u[d]}),l.push(f.prototype.import.call(e,p.module,n))}return Promise.all(l).then(function(e){for(var t=0;t1?o instanceof Array?r[n]=[].concat(o):"object"==typeof o?r[n]=be(o,t-1):"packageConfig"!==n&&(r[n]=o):r[n]=o}return r}function we(e,t){var r=e[t];return r instanceof Array?e[t].concat([]):"object"==typeof r?be(r,3):e[t]}function xe(e){if(e){if(-1!==Or.indexOf(e))return we(this[St],e);throw new Error('"'+e+'" is not a valid configuration name. Must be one of '+Or.join(", ")+".")}for(var t={},r=0;r "+o.paths[a]+" is no longer supported as wildcards are deprecated."),delete o.paths[a])}if(e.defaultJSExtensions&&R.call(o,"The defaultJSExtensions configuration option is deprecated.\n Use packages defaultExtension instead.",!0),"boolean"==typeof e.pluginFirst&&(o.pluginFirst=e.pluginFirst),e.map)for(var a in e.map){var s=e.map[a];if("string"==typeof s){var u=Q.call(r,o,s,void 0,!1,!1);"/"===u[u.length-1]&&":"!==a[a.length-1]&&"/"!==a[a.length-1]&&(u=u.substr(0,u.length-1)),o.map[a]=u}else{m=(m=Q.call(r,o,"/"!==a[a.length-1]?a+"/":a,void 0,!0,!0)).substr(0,m.length-1);var l=o.packages[m];l||((l=o.packages[m]=Ee()).defaultExtension=""),Oe(l,{map:s},m,!1,o)}}if(e.packageConfigPaths){for(var c=[],f=0;ft.index)return!0;return!1}It.lastIndex=tr.lastIndex=rr.lastIndex=0;var r,n=[],o=[],i=[];if(e.length/e.split("\n").length<200){for(;r=rr.exec(e);)o.push([r.index,r.index+r[0].length]);for(;r=tr.exec(e);)t(o,r)||i.push([r.index+r[1].length,r.index+r[0].length-1])}for(;r=It.exec(e);)if(!t(o,r)&&!t(i,r)){var a=r[1].substr(1,r[1].length-2);if(a.match(/"|'/))continue;n.push(a)}return n}function Fe(e){if(-1===nr.indexOf(e)){try{var t=st[e]}catch(t){nr.push(e)}this(e,t)}}function Ke(e){if("string"==typeof e)return q(e,st);if(!(e instanceof Array))throw new Error("Global exports must be a string or array.");for(var t={},r=0;r1;)e=e[n=o.shift()]=e[n]||{};void 0===e[n=o.shift()]&&(e[n]=r)}function Ve(e,t){var r=e.match(br);if(r)for(var n=r[0].match(wr),o=0;o