Compiling two files with RequireJS Optimize - requirejs

I am trying to specify compilation for two files in the build.js file for RequireJS optimizer. But only the last file gets optimized. Here's the build.js file:
({
baseUrl: "..",
name: "client/TestA",
out: "full.js",
findNestedDependencies: true
},{
baseUrl: "..",
name: "client/TestB",
out: "fullB.js",
findNestedDependencies: true
})
In this case only the last entry client/TestB is getting built. I need the require Optimizer to build both.

Where did you found this format of build.js file? Maybe you need something like modules field?
It should be something like this:
({
baseUrl: "..",
dir : './out' // required when using modules, instead 'out' field
modules: [
{
name: "client/TestA"
},
{
name: "client/TestB"
}
],
findNestedDependencies: true
});

Related

Include locales and stores on compiled mfe with vite plugin federation

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);

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 to use file naming in pascal case of extensions .tsx, and .jsx in my .eslintrc.js

I am using this library: eslint-plugin-filenames
I'm new with this eslintrc stuff, and I want to know how to make my files with .tsx or .jsx extensions forced to be called in PascalCase format.
For example, I get this file in my project: src/pages/my_component.tsx.
I need MyComponent.tsx insted of my_component.tsx
This is the content of my file .eslintrc.js
/* eslint-env node */
module.exports = {
root: true,
env: {
node: true,
},
parser: '#typescript-eslint/parser',
plugins: ['#typescript-eslint', 'prettier', 'json', 'jest','filenames'], // I include "filenames"
extends: [
'eslint:recommended',
'plugin:prettier/recommended',
'plugin:jest/recommended',
'plugin:#typescript-eslint/eslint-recommended',
'plugin:#typescript-eslint/recommended',
],
rules: {
'linebreak-style': ['error', 'unix'],
quotes: ['error', 'single'],
},
};
I have read the documentation and I don't know how to specify my need, something like this:
rules: {"filenames/match-exported": [ 2, "pascal" ]} //how to define PascalCase to `.tsx` or `.jsx`
How can do it work?

include a config file in webpack bundle

In my webpack project I want to bundle my project and include an example usage file with it. However when I bundle my project in this form
module.exports = {
entry: {
main: './src/main.js',
about: './src/pages/config.js'
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js',
library: 'report' //makes this a global variable we can call from basic javascript page,
devtool: 'source-map',
devServer: {
port: 3001,
clientLogLevel: 'none',
stats: 'errors-only'
},
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader'] //npm install --save-dev style-loader css-loader
}
]
},
plugins: [
new CleanWebpackPlugin({ cleanStaleWebpackAssets: false }),
new HtmlWebpackPlugin({
title: 'ESS Map Learning',
}),
],
};
},
The outputted file in the dist is converted or loaded into bundled code and is unreadable as an example. I am trying to find a way to load this file so it is not changed and sits in the bundle in its original format
If you want to include an example usage file along with your bundle, you can try the following two ways:
1. use CopyWebpackPlugin
With this plugin, you can copy specific files from your source project into your output folder.
First you need to install the plugin:
npm install --save-dev copy-webpack-plugin
Then in your webpack configuration file:
const CopyPlugin = require("copy-webpack-plugin");
module.exports = {
plugins: [
new CopyPlugin([
{
from: "path/to/some-example.js",
to: "" // leave blank if you want to keep the folder hierachy as in the source code, otherwise specify an output path
},
]),
]
}
More about the plugin:
Webpack Plugins: CopyWebpackPlugin
2. use the "Asset Modules" configuration
module.exports = {
module: {
rules: [
{
test: /example\.js/, // regex to match your source example file path
type: 'asset/resource', // files with this type will be copied to your output folder
generator: {
filename: 'examples/[name][ext]', // you can give a desired name for your output file, or webpack will defaultly name it with hash value
}
}
]
},
// rest of your webpack configuration
// ...
}
Caveats: I think webpack will never process your example file if it is not a dependency of any of your entry points (which is very likely the case). In this sense I guess using the CopyWebpackPlugin is more reliable.
More about asset modules:
Webpack Guides: Asset Management
Webpack Guides: Asset Modules

Renaming the optimized files in requirejs folder level optimization

I'm using requirejs with Grunt in my project. I could able to successfully perform the folder level optimization through grunt-requirejs tool as below.
requirejs : {
std: {
options: {
mainConfigFile: 'src/js/main.js',
appDir: "src",
baseUrl: "js",
dir: "dist",
modules: [
{
name: "main"
}
],
removeCombined: true,
wrap: true,
almond: true,
replaceRequireScript: [{
files: ['dist/index.html'],
module: 'main'
}]
}
}
}
All the js files are concatenated and minified in main.js and css files in style.css. How can I rename these files main.js and style.css into something like app.min.js and app.min.css. Can I able to accomplish this using r.js or I've to use some external plugin?

Resources