Open mstruensee opened 2 years ago
so far this is a solution that works ... but hackkkkkky ...
in webpack.config in root-config, set window.endpoints inside html plugin ... index.ejs
<script> window.endpoints = <%= endpoints %> </script>
webpack.config.js
new HtmlWebpackPlugin({
inject: false,
template: "src/index.ejs",
templateParameters: {
endpoints: JSON.stringify(endpoints),
},
}),
in webpack.config in app1, pass endpoints as customProps
webpack.config.js
const defaultConfig = singleSpaDefaults({
orgName,
projectName,
webpackConfigEnv,
argv,
standaloneOptions: {
customProps: {
endpoints
}
}
});
grab endpoints inside of the mount lifecycle and set window.endpoints (if not set, as all front end services will be running this logic)
org-app1.tsx
export const mount = (props) => {
if(!window.endpoints) {
console.log("setting endpoints!", props.endpoints)
window.endpoints = props.endpoints
} else {
console.log("endpoints already set")
}
return lifecycles.mount(props);
}
this works for standalone and for deployed to environment ... not ideal but works, as all apps can get host endpoints from window.endpoints
let me know if there is or can or will be an easier way :D
update: this has 1 flaw so far, when trying to use redux toolkit query, when trying to setup createApi
, fetchBaseQuery
seems to be compiled and generated at import time, so grabbing the baseUrl
from window.endpoints
throws an error as window.endpoints
is undefined as it is not set until mount
when doing development in standalone
mode. I think the best solution would be to have it put on via HtmlWebpackPlugin
in the webpack config, just like the root-config
, this way it is there during start/load/import.
If HtmlWebpackPlugin
options can be passed down just like standaloneOptions
then when adding a src/index.ejs
, then templateParameters
should be able to be referenced and then swapped/replaced prior to standalone app loading. This would be a good approach as it is also how the root config does it.
update:
modifying webpack-config-single-spa
and adding options to the HtmlWebpackPlugin
, worked successfully.
const defaultConfig = singleSpaDefaults({
orgName,
projectName,
webpackConfigEnv,
argv,
htmlWebpackPluginOptions: {
templateParameters: {
endpoints: JSON.stringify(endpoints),
},
}
});
https://github.com/single-spa/create-single-spa/blob/main/packages/webpack-config-single-spa/lib/webpack-config-single-spa.js#L126
!isProduction && !opts.disableHtmlGeneration && new HtmlWebpackPlugin(opts.htmlWebpackPluginOptions? opts.htmlWebpackPluginOptions : null),
can there be a feature request for htmlWebpackPluginOptions
?
any update on this?
bump @filoxo
a temporary solution that seems to be working
const {merge} = require("webpack-merge")
const singleSpaDefaults = require("webpack-config-single-spa-react-ts")
const packageJson = require("./package.json")
const {fetchServiceEndpoints} = require("./util")
const HtmlWebpackPlugin = require("html-webpack-plugin")
const { groups: {orgName, projectName} } = /@(?<orgName>.*)\/(?<projectName>.*)/.exec(packageJson.name)
module.exports = fetchServiceEndpoints().then((endpoints) => {
class ExtendHtmlWebpackPlugin extends HtmlWebpackPlugin {
constructor() {
super({
templateParameters: {
title: projectName,
serviceEndpoints: JSON.stringify(endpoints),
},
})
}
}
return (webpackConfigEnv, argv) => {
const defaultConfig = singleSpaDefaults({
orgName,
projectName,
webpackConfigEnv,
argv,
HtmlWebpackPlugin: ExtendHtmlWebpackPlugin,
})
return merge(defaultConfig, {
output: {
clean: true,
},
devServer: {
server: "https",
},
})
}
})
this now unlocks the capability to have a custom html file used for the generation of the standalone component, other stuff can be added, like pattern library classes, themes, etc. Currently all documentation only allows all this stuff to work via root-config, and not in standalone mode for individual components.
Sorry about the lack of response, I hadn't seen this ping.
I wonder if webpack-merge's mergeWithCustomize can be used to clean this up a little bit:
const { mergeWithCustomize, unique } = require('webpack-merge');
const singleSpaDefaults = require('webpack-config-single-spa');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const merge = mergeWithCustomize({
customizeArray: unique(
'plugins',
['HtmlWebpackPlugin'],
(plugin) => plugin.constructor && plugin.constructor.name
),
});
which I've used in an example repo that I maintain here: https://github.com/filoxo/single-spa-example-rxjs-shared-state/blob/main/packages/root-config/webpack.config.js#L5-L11 except that that example doesn't make use of standalone mode. Maybe that could work for this case still though?
I think your solution should be taken and made into an org-specific single-spa-webpack-config package to share across your applications. Its basically just taking our config and wrapping with your org's needs/opinions/rules.
Thanks for the reply! I will give that approach a try ... Yeah it is hard to be 100% standalone, in my case it is just the theme, so you can do the development without it, it just looks different :D
I'm wanting to use standalone mode in a similar fashion, and I can't get it working with either mergeWithCustomize or instantiating an extended HtmlWebpackPlugin class.
I'd vote for going with the options param for HtmlWebpackPlugin, similar to standaloneOptions.
And/or the ability to expand to be not limited to 1 html file that gets generated with the various import-map etc
I disagree with expanding the configuration API... mostly because where does it end? The base single-spa-webpack-config includes other plugins too so if we allow passing through all options for one plugin, we'd probably have to allow all options for all plugins. This is why I prefer webpack-merge: you can extend the inner parts of the config without it having to create a top-level API for overrides.
Alternatively, using webpack-chain
could provides a different way of extending plugin options that you might prefer.
is there a way currently to inject something like ... html or templateParameters into the HtmlWebpackPlugin ... my use case is ... the root-config is setting
API_ENDPOINTS
on the window for all other micro services to use, works great, they have access to it and everything ... problem is standalone development ... they can't get the endpoint as its not on the windowor even a feature to set window variables?
https://github.com/single-spa/create-single-spa/blob/main/packages/webpack-config-single-spa/lib/webpack-config-single-spa.js#L126
might have to change the design to pass it as a customProp as that is supported in the standalone-single-spa-webpack-plugin
EDIT: attempted this, there is no way for me to send customProps from webpack.config inside the root-config ... can do that from a non root-config, as it uses the standalone-single-spa-webpack-plugin, but in root-config, that is disabled.
https://github.com/single-spa/standalone-single-spa-webpack-plugin#customizing-the-html-file ^^ can i use teplateParamters and put it in the index file and pass to standalone-single-spa-webpack-plugin?