Skip to content

Instantly share code, notes, and snippets.

@JFGHT
Last active June 12, 2024 11:30
Show Gist options
  • Save JFGHT/86cff139c7a721d4f2bfbcdef288a101 to your computer and use it in GitHub Desktop.
Save JFGHT/86cff139c7a721d4f2bfbcdef288a101 to your computer and use it in GitHub Desktop.
single-spa vue2 & vue3
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Root Config</title>
<link rel="icon" href="/single-spa.svg">
<!--
This CSP allows any SSL-enabled host and for arbitrary eval(), but you should limit these directives further to increase your app's security.
Learn more about CSP policies at https://content-security-policy.com/#directive
-->
<!-- <meta http-equiv="Content-Security-Policy" content="default-src 'self' https: localhost:*; script-src 'unsafe-inline' 'unsafe-eval' https: localhost:*; connect-src https: localhost:* ws://localhost:*; style-src 'unsafe-inline' https:; object-src 'none';"> -->
<!-- If you wish to turn off import-map-overrides for specific environments (prod), uncomment the line below -->
<!-- More info at https://github.com/joeldenning/import-map-overrides/blob/master/docs/configuration.md#domain-list -->
<!-- <meta name="import-map-overrides-domains" content="denylist:prod.example.com" /> -->
<script>
if (HTMLScriptElement.supports && !HTMLScriptElement.supports('importmap')) {
alert('Your browser does not support import maps.');
throw new Error('Your browser does not support import maps.');
}
</script>
{{#if isLocal}}
<script type="importmap">
{
"imports": {
"@core": "/src/main.ts",
"web": "//localhost:3000/web/src/main.ts",
"legacy": "//localhost:8080/legacy/main.js"
}
}
</script>
{{/if}}
</head>
<body>
<noscript>
You need to enable JavaScript to run this app.
</noscript>
<script>
import('@core');
</script>
</body>
</html>
import { registerApplication, start } from 'single-spa';
import {
constructApplications,
constructRoutes,
constructLayoutEngine
} from 'single-spa-layout';
const routes = constructRoutes({
routes: [
{
type: "route",
path: "/web",
routes: [{ type: "application", name: "web" }],
},
{
type: "route",
path: "/legacy",
routes: [{ type: "application", name: "legacy" }],
},
],
});
const applications = constructApplications({
routes,
loadApp: ({ name }) => import(/* @vite-ignore */ name)
});
const layoutEngine = constructLayoutEngine({ routes, applications });
applications.forEach(registerApplication);
layoutEngine.activate();
start();
import fs from 'fs';
import type { PluginOption } from 'vite';
import { defineConfig, loadEnv, UserConfigExport } from 'vite';
import handlebars from 'vite-plugin-handlebars';
export default defineConfig(({ mode }) => {
const env = loadEnv(mode, process.cwd());
const config: UserConfigExport = {
base: './',
server: {
port: 9000
},
build: {
rollupOptions: {
input: {
index: './index.html',
'core': './src/main.ts'
},
output: {
format: 'esm',
entryFileNames: '[name].js',
assetFileNames: 'assets/[name][ext]',
globals: {
'web': 'web',
'legacy': 'legacy',
'single-spa-layout': 'singleSpaLayout'
}
},
preserveEntrySignatures: 'strict',
external: ['web', 'legacy', 'single-spa-layout']
}
},
plugins: [
handlebars({
context: {
isLocal: mode === 'development'
}
}) as unknown as PluginOption,
{
name: 'vite-plugin-build-rm-file',
apply: 'build',
enforce: 'post',
closeBundle() {
fs.unlinkSync(`${env.VITE_OUTDIR}/index.js`);
}
}
]
};
if (mode === 'docs') {
config.build.outDir = env.VITE_OUTDIR;
}
return config;
});
// Not included in core-js https://github.com/zloirock/core-js/issues/386
// ------------ Polyfills ------------
// import 'core-js/stable';
import 'core-js/stable/object/assign';
import 'core-js/stable/array/values';
// IntersectionObserver polyfill for v-lazy-image
import 'intersection-observer';
// Rest
import { auth, db } from './firebase';
import vueStart from './vue';
import './icons/icons';
const vueLifecycles = vueStart(auth, db);
export const bootstrap = vueLifecycles.bootstrap;
export const mount = vueLifecycles.mount;
export const unmount = vueLifecycles.unmount;
const StyleLintPlugin = require('stylelint-webpack-plugin');
const path = require('path');
// const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const whitelabelConfig = require('./whitelabel.config');
const environment = process.env.NODE_ENV;
module.exports = {
publicPath: environment === 'development' ? 'http://localhost:8080/legacy/' : '/legacy/',
devServer: {
headers: {
'Access-Control-Allow-Origin': '*',
},
},
css: {
// Fixing sass-loader problem with sourcemaps
// https://github.com/webpack-contrib/sass-loader/issues/731
// loaderOptions: {
// sass: {
// sourceMap: false,
// },
// },
// Activating css sourcemaps
sourceMap: environment === 'development',
},
// Fixing CircleCi Bug related to thread-loader
parallel: process.env.CIRCLECI ? 3 : true,
configureWebpack: {
entry: path.resolve(__dirname, './src/main.ts'),
output: {
filename: '[name].js',
path: path.resolve(__dirname, 'dist'),
// chunkFilename: '[name].js',
library: {
type: 'module',
},
libraryTarget: 'module',
chunkLoading: false,
module: true,
devtoolNamespace: 'legacy',
},
experiments: {
outputModule: true,
},
resolve: {
alias: {
// 'vue$': 'vue/dist/vue.esm.js',
scssVars: path.resolve(__dirname, './src/scss/variables/_base.scss'),
assets: path.resolve(__dirname, './src/assets/'),
brandVariables: path.resolve(__dirname, whitelabelConfig.scssVariables),
},
},
plugins: [
new StyleLintPlugin({
emitErrors: false,
syntax: 'scss',
}),
],
optimization: {
splitChunks: false,
},
},
};
import { h, createApp } from "vue";
import singleSpaVue from "single-spa-vue";
import App from "./app.vue";
const vueLifecycles = singleSpaVue({
createApp,
appOptions: {
render() {
return h(App, {
// single-spa props are available on the "this" object. Forward them to your component as needed.
// https://single-spa.js.org/docs/building-applications#lifecycle-props
name: this.name,
// @ts-ignore
mountParcel: this.mountParcel,
// @ts-ignore
singleSpa: this.singleSpa,
});
},
},
handleInstance: (app) => {
// app.use(router);
},
});
export const bootstrap = vueLifecycles.bootstrap;
export const mount = vueLifecycles.mount;
export const unmount = vueLifecycles.unmount;
import { fileURLToPath, URL } from "node:url";
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
// https://vitejs.dev/config/
export default defineConfig({
build: {
rollupOptions: {
input: "src/main.ts",
output: {
format: "esm",
},
preserveEntrySignatures: "strict",
},
},
server: {
origin: 'http://localhost:3000',
port: 3000,
strictPort: true,
},
base: "/web/",
plugins: [vue()],
resolve: {
alias: {
"@": fileURLToPath(new URL("./src", import.meta.url)),
},
},
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment