Include locales and stores on compiled mfe with vite plugin federation - vite

I'm doing a microfrontend project using vite plugin federation. The mfe childs uses i18n and pinia.
After compiling and importing the mfe childs into de host, it doesn't work because it can't resolve de dependencies (i18n and pinia).
Error with i18n:
Uncaught TypeError: _ctx.$t is not a function
Error with pinia:
Uncaught Error: [🍍]: getActivePinia was called with no active Pinia. Did you forget to install pinia?
const pinia = createPinia()
app.use(pinia)
To resolve it, it's not enough installing these dependencies into the host, i also need to config i18n with the same json structure and pinia with the same stores structures.
Due to this, i'll have some duplicated files in different repositories so i think it's not the best way to handle this.
Do you have any workaround idea?
(mfe-child) vite.config.ts
export default defineConfig({
plugins: [
vue(),
federation({
name: "mfe-boilerplate",
filename: "remoteEntry.js",
exposes: {
"./ExampleView": "./src/modules/example-module/views/ExampleView.vue",
},
shared: ["vue", "vue-i18n", "pinia"],
}),
vueI18n({
include: path.resolve(__dirname, "./src/locales/**"),
compositionOnly: true,
}),
],
build: {
minify: false,
}
});
(mfe-host) vite.config.ts
export default defineConfig({
plugins: [
vue(),
federation({
name: "host-app",
remotes: {
mfe_boilerplate: "http://localhost:4174/assets/remoteEntry.js",
},
shared: ["vue", "vue-i18n", "pinia"],
}),
],
});
Additional config to make i18n work:
(mfe-host) main.ts
const i18n = createI18n({
locale: "en",
messages: { // this is the same JSON structure and content from mfe-child
en: {
"mfe-child-page-title": "Title from host"
},
},
});
app.use(i18n);

Related

How to override the rollup output.format setting in vite?

I'm trying to solve the Vite build error I get:
RollupError: Invalid value "iife" for option "output.format" - UMD and IIFE output formats are not supported for code-splitting builds.
The file name reported with this error points to
my web worker code, so I assumed that this setting belongs to the worker section in vite.config.ts:
import { defineConfig } from "vite";
import preact from "#preact/preset-vite";
import basicSsl from "#vitejs/plugin-basic-ssl";
import { NodeGlobalsPolyfillPlugin } from "#esbuild-plugins/node-globals-polyfill";
import { NodeModulesPolyfillPlugin } from "#esbuild-plugins/node-modules-polyfill";
import rollupNodePolyFill from "rollup-plugin-node-polyfills";
export default defineConfig({
plugins: [
preact(),
basicSsl(),
],
server: {
port: 3001,
https: true,
},
optimizeDeps: {
esbuildOptions: {
// Node.js global to browser globalThis
define: {
global: "globalThis",
},
// Enable esbuild polyfill plugins
plugins: [
NodeGlobalsPolyfillPlugin({
process: true,
buffer: true,
}),
NodeModulesPolyfillPlugin(),
],
},
},
worker: {
rollupOptions: {
output: {
format: "esm",
},
},
},
build: {
rollupOptions: {
plugins: [
// Enable rollup polyfills plugin
// used during production bundling
rollupNodePolyFill(),
],
output: {
format: "esm",
},
},
},
});
Additionally, I set the output format in the build rollup options. However, neither of the two settings are applied and I still get the said error.
What is the correct way to change the rollup output format setting in Vite?
The worker output format must be specified directly in the worker config key, not its rollup options:
import { defineConfig } from "vite";
import preact from "#preact/preset-vite";
import basicSsl from "#vitejs/plugin-basic-ssl";
import { NodeGlobalsPolyfillPlugin } from "#esbuild-plugins/node-globals-polyfill";
import { NodeModulesPolyfillPlugin } from "#esbuild-plugins/node-modules-polyfill";
import rollupNodePolyFill from "rollup-plugin-node-polyfills";
export default defineConfig({
plugins: [
preact(),
basicSsl(),
],
server: {
port: 3001,
https: true,
},
optimizeDeps: {
esbuildOptions: {
// Node.js global to browser globalThis
define: {
global: "globalThis",
},
// Enable esbuild polyfill plugins
plugins: [
NodeGlobalsPolyfillPlugin({
process: true,
buffer: true,
}),
NodeModulesPolyfillPlugin(),
],
},
},
worker: {
format: "es",
},
build: {
rollupOptions: {
plugins: [
// Enable rollup polyfills plugin
// used during production bundling
rollupNodePolyFill(),
],
output: {
format: "esm",
},
},
},
});

How to publish webpack on Vite properly

Im trying to publish locally a webpack on Vite to test micro front ends, but when I run my host app, it doesn't find the remoteEntry.js, and thats because when I try to access my remoteEntry.js, it doesn't exist. Does anyone know why?
This is my vite.conf on the remote
import { defineConfig } from "vite";
import vue from "#vitejs/plugin-vue";
// https://vitejs.dev/config/
// vite.config.js
import federation from "#originjs/vite-plugin-federation";
export default defineConfig({
server: {
port: 8080,
},
plugins: [
vue(),
federation({
name: "myLib",
filename: "remoteEntry.js",
// Modules to expose
exposes: {
"./Counter": "./src/components/Counter.vue",
},
remotes: {},
shared: ["vue"],
}),
],
});
And this is the config on the remote side:
import { defineConfig } from 'vite'
import vue from '#vitejs/plugin-vue'
import federation from "#originjs/vite-plugin-federation";
export default defineConfig({
server: {
port: 8081,
},
plugins: [
vue(),
federation({
name: "myApp",
remotes: {
myLib: "http://localhost:8080/assets/remoteEntry.js",
},
shared: ["vue"],
}),
],
});
When i try to access my dependencies on the host side, this error pops on the console:
Uncaught (in promise) TypeError: Failed to fetch dynamically imported module: http://localhost:8080/assets/remoteEntry.js
Thank you very much

How to wrap Vite build in IIFE and still have all the dependencies bundled into a single file?

I'm building a chrome extension using Vite as my build tool. The main problem is during minification and mangling there are a lot of global variables created. After injecting my script to the page they conflict with already defined variables on window object.
I imagine the perfect solution would be to have my entire script wrapped in IIFE. I tried using esbuild.format = 'iife'. The resulting build is in fact wrapped in IIFE, however all the imports are not inlined. Instead resulting script is like 15 lines long with a bunch of require statements, which obviously does not work in the browser.
This is my config file:
export default defineConfig({
plugins: [
vue(),
],
esbuild: {
format: 'iife',
},
build: {
emptyOutDir: false,
rollupOptions: {
input: resolve(__dirname, './src/web/index.ts'),
output: {
dir: resolve(__dirname, './dist'),
entryFileNames: 'web.js',
assetFileNames: 'style.css',
},
},
},
resolve: {
alias: {
'#': resolve(__dirname, './src'),
},
},
});
I'm currently using this hack so to say to wrap my build in IIFE (for this I removed the esbuild.format option).
Hey I am doing the exact same thing! And I also noticed the unminified variables and functions can clash with random code in a webpage.
From what I researched myself on this topic, you shouldn't change esbuild build options with Vite as that will prevent Rollup from transforming the output. Instead, you should use format: 'iife' in the rollupOptions of your vite.config. However, in my case (and yours I believe), I have to output multiple bundles since the extension code can't share modules amongst each other. Which will crash when you set the format to 'iife' due to:
Invalid value for option "output.inlineDynamicImports" - multiple inputs are not supported when "output.inlineDynamicImports" is true.
The only solution in my case seems to be to either use multiple vite.configs (I already have two) for each of my bundle with single input entry point and format as 'iife'. Or, as you did, just write the self-invoking function yourself with some hacky script. Seems though there aren't any perfect solutions as of now.
EDIT: Okay, got it working. This is my vite.config.ts (the project):
import { defineConfig } from 'vite'
import { svelte } from '#sveltejs/vite-plugin-svelte'
import tsconfigPaths from 'vite-tsconfig-paths'
import path from 'path'
/** #type {import('vite').UserConfig} */
export default defineConfig({
plugins: [svelte({}), tsconfigPaths()],
build: {
minify: false,
rollupOptions: {
output: {
chunkFileNames: '[name].js',
entryFileNames: '[name].js'
},
input: {
inject: path.resolve('./src/inject.ts'),
proxy: path.resolve('./src/proxy.ts'),
'pop-up': path.resolve('./pop-up.html')
},
plugins: [
{
name: 'wrap-in-iife',
generateBundle(outputOptions, bundle) {
Object.keys(bundle).forEach((fileName) => {
const file = bundle[fileName]
if (fileName.slice(-3) === '.js' && 'code' in file) {
file.code = `(() => {\n${file.code}})()`
}
})
}
}
]
}
}
})
Okay, I made it working with this config:
export default defineConfig({
plugins: [
vue(),
],
build: {
emptyOutDir: false,
rollupOptions: {
input: resolve(__dirname, './src/web/index.ts'),
output: {
format: 'iife',
dir: resolve(__dirname, './dist'),
entryFileNames: 'web.js',
assetFileNames: 'style.css',
},
},
},
resolve: {
alias: {
'#': resolve(__dirname, './src'),
},
},
});
They key part is format: 'iife' inside build.rollupOptions.output.

How do I use `unpkg` with ViteJS?

I'm migrating my Vue plugin from Vue CLI to Vitejs.
With vue-cli-service build I generate three files: index.common.js, index.umd.js and index.umd.min.js
In package.json I refer to these files with:
"main": "dist/index.common.js",
"unpkg": "dist/index.umd.min.js",
But now migrating to ViteJS npm run build creates js files with random strings index.25e1eb44.js.
How do I use unpkg with ViteJS in package.json?
By reading other code, I found a good solution:
import { defineConfig } from 'vite';
import vue from '#vitejs/plugin-vue';
import cssInjectedByJsPlugin from 'vite-plugin-css-injected-by-js';
const path = require('path');
// https://vitejs.dev/config/
export default defineConfig({
build: {
lib: {
entry: path.resolve(__dirname, 'src/index.js'),
name: 'VueResponsiveVideoBackgroundPlayer',
fileName: 'vue-responsive-video-background-player',
},
rollupOptions: {
external: ['vue'],
output: {
// Provide global variables to use in the UMD build
// Add external deps here
globals: {
vue: 'Vue',
},
},
},
},
plugins: [
vue(),
cssInjectedByJsPlugin(),
],
});
For more, read here: https://vitejs.dev/config/build-options.html#build-commonjsoptions

Cannot find module 'sanitize.css/page.css'

While building the gatsby project, I faced this kind of error.
yarn develop
ERROR #98123 WEBPACK
Generating development JavaScript bundle failed
Cannot find module 'sanitize.css/page.css'
Require stack:
- D:\UpworkJobs\Nate\dci-gatsby-importexport\node_modules\postcss-normalize\dist\index.cjs.js
File: src\css\preview.css
failed Building development bundle - 366.725s
Here is a screenshot of the error log.
These kinds of errors occur even if I removed all CSS codes from the style files.
It seems importing CSS files is not working. If I didn't import the CSS files, the errors go away.
Here are all codes of gatsby-config.js
let systemvars = false;
if (process.env.NODE_ENV === "production") {
systemvars = true;
}
require("dotenv").config({
path: `.env.${process.env.NODE_ENV}`,
systemvars
});
// Gatsby automatically sets NODE_ENV to `development` or `production` when running `gatsby develop` or `gatsby build`, respectively.
// Thus make sure you have .env.development or .env.production setup (unless your CI/build env vars are already set globally)
const AliasConfig = require("./alias.config.js");
module.exports = {
siteMetadata: {
title: `DCI DigiGuide Print`,
description: `DCI DigiGuide Printable Version`,
author: `#designbycosmic`,
siteUrl: process.env.SITE_URL,
},
plugins: [
//
// * App Functionality Plugins
//
// eslint plugin
{
resolve: "gatsby-plugin-eslint",
options: {
test: /\.js$|\.jsx$/,
exclude: /(node_modules|.cache|public)/,
stages: ["develop"],
options: {
maxWarnings: undefined,
emitWarning: true,
failOnError: false,
failOnWarning: false,
},
},
},
// allows content to be placed in head
`gatsby-plugin-react-helmet`,
// adds web manifest for some pwa functionality
{
resolve: `gatsby-plugin-manifest`,
options: {
name: `gatsby-dci-digiguide-print`,
short_name: `DigiGuidePrint`,
start_url: `/`,
background_color: `#222c47`,
theme_color: `#222c47`,
display: `minimal-ui`,
icon: `./src/images/favicon.png`, // This path is relative to the root of the site.
},
},
// allow alias imports
{
resolve: "gatsby-plugin-alias-imports",
options: {
alias: AliasConfig.map,
extensions: AliasConfig.extensions,
},
},
// inline svgs instead of converting them to base64
{
resolve: "gatsby-plugin-react-svg",
options: {
rule: {
include: /svg/,
},
},
},
`gatsby-plugin-postcss`,
`gatsby-plugin-material-ui`,
// Craft CMS configuration
{
resolve: `gatsby-source-graphql`,
options: {
url: process.env.CRAFT_API_URL,
typeName: "Craft",
fieldName: "craft",
headers: {
Authorization: `bearer ${process.env.CRAFT_API_TOKEN}`,
},
},
},
// Get build date
{
resolve: `gatsby-plugin-build-date`,
options: {
formatAsDateString: false,
},
},
],
};
Help me to solve this problem.
In my case I was able to solve by adding the following configuration in package.json.
"resolutions": {
"sanitize.css": "12.0.1"
},
Finally, this problem has been solved.
Using yarn instead of using npm solved the problem.
Remove node_modules and yarn install
After that, the problem has gone away.
Thank you.

Resources