Uncaught ReferenceError: process is not defined after vite update, why? - reactjs

I have a react/typescript app and before I updated vite I had this solution to check either env is development or production by this code:
function getEnvironment(): "production" | "development" {
if (process.env.NODE_ENV === "production") {
return "production";
}
return "development";
}
type EnvUrl = { development: string; production: string };
const API_URL: EnvUrl = {
development: "http://localhost:5173/api/endpoint",
production: "https://ingress-url/api/endpoint",
};
export const apiUrl = API_URL[getEnvironment()];
But after i updated vite to version 3.1.0 I got error when serving production build with following error: Uncaught ReferenceError: process is not defined.
By vite config is:
import react from "#vitejs/plugin-react";
import { resolve } from "path";
import { rollupImportMapPlugin } from "rollup-plugin-import-map";
import { terser } from "rollup-plugin-terser";
import { ConfigEnv } from "vite";
import viteCompression from "vite-plugin-compression";
import cssInjectedByJsPlugin from "vite-plugin-css-injected-by-js";
import { viteMockServe } from "vite-plugin-mock";
import { UserConfigExport } from "vitest/config";
const reactUrl = "my-cdn-url/react/18/esm/index.js";
const reactDomUrl = "my-cdn-url/react-dom/18/esm/index.js";
const imports = {
react: reactUrl,
"react-dom": reactDomUrl,
};
export default ({ command }: ConfigEnv): UserConfigExport => ({
plugins: [
react(),
terser(),
cssInjectedByJsPlugin(),
viteCompression({
algorithm: "gzip",
}),
viteCompression({
algorithm: "brotliCompress",
}),
viteMockServe({
mockPath: "mock",
localEnabled: command === "serve",
}),
{
...rollupImportMapPlugin([{ imports }]),
enforce: "pre",
apply: "build",
},
],
build: {
lib: {
entry: resolve(__dirname, "src/Mikrofrontend.tsx"),
name: "sokos-attestasjon-frontend",
formats: ["es"],
fileName: () => `bundle.js`,
},
},
test: {
globals: true,
environment: "jsdom",
deps: {
inline: ["#testing-library/user-event"],
},
},
});
Is there another way to fix the problem or am I missing something in my vite.config.js ? If its another solution after upgrade, what the recommended one so my application behave the same as before?
Thank you.

Use import.meta.env.MODE to get the mode string:
if (import.meta.env.MODE === "production") {
return "production";
}
Or more simply, use import.meta.env.PROD to get a Boolean indicating production mode:
if (import.meta.env.PROD) {
return "production";
}

Related

MFE module federation cannot find module for remote child import

Im trying to build out a micro frontend for the first time so my main application can support a sub application. I have it all working when everything is just rendering App.tsx (remote) but as soon as I try and render a child within the remote application I get the Cannot find module error from webpack
Container craco.congig.js
/* eslint-disable #typescript-eslint/no-var-requires */
const CracoEsbuildPlugin = require('craco-esbuild');
const { ModuleFederationPlugin } = require("webpack").container;
const deps = require("./package.json").dependencies;
module.exports = {
webpack: {
plugins: {
add: [
new ModuleFederationPlugin({
name: "Dashboard",
remotes: {
DigitalCanopy: "DigitalCanopy#//localhost:3001/remoteEntry.js",
},
shared: {
react: {
singleton: true,
strictVersion: true,
requiredVersion: deps['react']
},
"react-dom": {
singleton: true,
strictVersion: true,
requiredVersion: deps['react-dom']
},
},
}),
],
},
...
My remote craco.config.js
/* eslint-disable #typescript-eslint/no-var-requires */
const CracoEsbuildPlugin = require('craco-esbuild');
const { ModuleFederationPlugin } = require("webpack").container;
const deps = require("./package.json").dependencies;
module.exports = {
devServer: {
port: 3001
},
webpack: {
plugins: {
add: [
new ModuleFederationPlugin({
name: "DigitalCanopy",
exposes: {
"./DigitalCanopy": "./src/App.tsx",
},
filename: "remoteEntry.js",
shared: {
react: { singleton: true },
"react-dom": { singleton: true },
},
}),
],
},
configure: (webpackConfig) => ({
...webpackConfig,
output: {
...webpackConfig.output,
publicPath: "auto",
},
}),
},
plugins: [
{
plugin: CracoEsbuildPlugin,
options: {
esbuildLoaderOptions: {
// Optional. Defaults to auto-detect loader.
loader: 'tsx', // Set the value to 'tsx' if you use typescript
target: 'es2018',
},
esbuildMinimizerOptions: {
target: 'es2018',
css: true, // if true, OptimizeCssAssetsWebpackPlugin will also be replaced by esbuild.
},
skipEsbuildJest: false, // Optional. Set to true if you want to use babel for jest tests,
esbuildJestOptions: {
loaders: {
'.ts': 'ts',
'.tsx': 'tsx',
},
},
},
},
],
};
My remote App.tsx
import { createTheme, ThemeProvider } from '#mui/material';
import React from 'react';
import './App.css';
import App1 from './App1';
const baseTheme = createTheme({
...MUI THEME STUFF
});
function App() {
return (
<ThemeProvider theme={baseTheme}>
<div className="App">Digital Canopy App</div>;
<App1 />
</ThemeProvider>
);
}
export default App;
This works and renders fine until I try and render <App1 />
Then I get this error Module not found: Error: Can't resolve './App1' in ...
Any ideas? I feel like this should just work. Importing children components from within the remote is pretty standard doesnt seem unique but I cannot find anything similar online which makes me think Im missing something obvious.
Thanks for the help
My issue was I was missing the .tsx extension on the import. I have no idea why that is required by the sub application. My build configs are identical for typescript and my main app does not require that. I'll dig in and try and figure out why

Parsing error: "parseOptions.project" has been set for #typescript-eslint/parser

I am using a vite community template (boilerplate) that use husky and when I try to git commit my local repository the console throw me this:
I have all the settings done as they were on the boilerplate. The only thing I change is the "pre-commit" file in the ".husky" folder:
This is my vite.config.ts file:
import { defineConfig } from "vite";
import type { UserConfig } from "vite";
import react from "#vitejs/plugin-react";
import legacy from "#vitejs/plugin-legacy";
import tsconfigPaths from "vite-tsconfig-paths";
import mkcert from "vite-plugin-mkcert";
export default defineConfig(({ command, mode }) => {
const config: UserConfig = {
server: {
https: true,
},
plugins: [
react(),
tsconfigPaths(),
legacy(),
mkcert({
source: "coding",
}),
],
build: {
rollupOptions: {
output: {
manualChunks: {
react: ["react"],
"react-dom": ["react-dom"],
},
},
},
},
};
return config;
});

Storybook fails to show stories

the problem we are encountering when trying to add storybook to our project is, that when we run development server, webpack builds every part of the app (resolves ~50,000 dependencies), therefore, when we run it, on network tab we can see unnecessary file downloaded (which contains entire app) that causes entire story (which is downloaded as separate file due to storyStoreV7 flag) to crash, because some lines of unnecessary bundle are raising errors (files aren't even required to display stories). Example error:
TypeError: Cannot read properties of undefined (reading 'CheckboxList')
at Module.CheckboxList (http://localhost:6007/js_components_index_tsx-node_modules_django-channels_dist_sync_recursive-node_modules_moment_-6a9914.iframe.bundle.js:35683:111)
at Module../js/forms/fields/checkbox-list/index.tsx (http://localhost:6007/js_components_index_tsx-node_modules_django-channels_dist_sync_recursive-node_modules_moment_-6a9914.iframe.bundle.js:41141:103)
at __webpack_require__ (http://localhost:6007/runtime~main.iframe.bundle.js:28:33)
at fn (http://localhost:6007/runtime~main.iframe.bundle.js:352:21)
at Module../js/forms/fields/index.js (http://localhost:6007/js_components_index_tsx-node_modules_django-channels_dist_sync_recursive-node_modules_moment_-6a9914.iframe.bundle.js:43187:73)
at __webpack_require__ (http://localhost:6007/runtime~main.iframe.bundle.js:28:33)
at fn (http://localhost:6007/runtime~main.iframe.bundle.js:352:21)
at Module../js/apps/admin/forms/add-reward-rule/index.tsx (http://localhost:6007/js_components_index_tsx-node_modules_django-channels_dist_sync_recursive-node_modules_moment_-6a9914.iframe.bundle.js:1726:71)
at __webpack_require__ (http://localhost:6007/runtime~main.iframe.bundle.js:28:33)
at fn (http://localhost:6007/runtime~main.iframe.bundle.js:352:21)
We found out, that when importing components with React.lazy issue is not present, we can use it this way, but it would be better to use it the "proper" way.
Storybook version: 6.5.0-alpha.42
.storybook/main.js
const webpack = require('webpack');
const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin')
const path = require('path');
const globImporter = require('node-sass-glob-importer');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
"stories": [
"../js/**/*.stories.*",
],
"addons": [
"#storybook/addon-links",
"#storybook/addon-essentials",
"#storybook/addon-interactions",
{
"name": '#storybook/preset-scss',
"options": {
"sassLoaderOptions": {
"sourceMap": true,
"sassOptions": {
"includePaths": [path.resolve(__dirname, '../js')],
"importer": globImporter(),
}
},
"cssLoaderOptions": {
"url": false,
}
}
}
],
"features": {
"storyStoreV7": true,
},
"framework": "#storybook/react",
"core": {
"builder": "webpack5"
},
"staticDirs": [path.resolve(__dirname, '../../static')],
"webpackFinal": async (config) => {
config.entry.push(path.resolve(__dirname, '../scss/main.scss'))
config.resolve.plugins = [
...(config.resolve.plugins || []),
new TsconfigPathsPlugin({
extensions: config.resolve.extensions,
}),
];
config.resolve.alias = {
...(config.resolve.alias || {}),
'#js': path.resolve(__dirname, '../js'),
}
config.plugins = [
...(config.plugins || []),
new webpack.ProvidePlugin({
process: 'process/browser',
Buffer: ['buffer', 'Buffer'],
}),
new MiniCssExtractPlugin({
filename: 'style.css'
}),
]
config.module.rules.push(
{
test: /\.svg$/i,
issuer: /\.[jt]sx?$/,
use: [{ loader: '#svgr/webpack', options: { ref: true } }],
}
)
return config
}
}
.storybook/preview.tsx
import { ThemeProvider, StyledEngineProvider } from '#mui/material/styles';
import { Parameters } from '#storybook/react'
import { HistoryRouter } from '../js/routes/history-router';
import { browserHistory } from '../js/routes/history';
import '../scss/main.scss';
import theme from '../js/theme'
export const decorators = [
(Story) => {
return <StyledEngineProvider injectFirst>
<ThemeProvider theme={theme}>
<HistoryRouter history={browserHistory}>
{Story()}
</HistoryRouter>
</ThemeProvider>
</StyledEngineProvider>
}
]
export const parameters: Parameters = {
actions: { argTypesRegex: "^on[A-Z].*" },
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/,
},
},
}
export const argTypes = { children: { type: 'string' }}
example story: Button.stories.tsx:
import React from 'react';
import { ComponentMeta, ComponentStory } from '#storybook/react';
import { Button } from './index';
export default {
component: Button,
} as ComponentMeta<typeof Button>;
const Template: ComponentStory<typeof Button> = (args) => {
return <Button {...args}>{args.children || 'Button'}</Button>;
};
export const Common = Template.bind({});
Common.args = { variant: 'primary' };
In our case, the issue was actually a circular dependency between a few files that used the component we wanted to create stories for.

Invalid value for prop `css` when using #emotion/react with Vite

I couldn't find any information on how to make #emotion/react work in Storybook when using Vite as a bundler in a React application.
I'm getting errors like Invalid value for prop 'css' in <div> tag in almost every story.
Even though, #emotion/react is working fine for the webapp itself.
Here's my vite.config.js configuration:
import { defineConfig } from 'vite';
import react from '#vitejs/plugin-react';
export default defineConfig({
esbuild: {
jsxFactory: 'jsx',
jsxInject: `import { jsx } from '#emotion/react'`,
},
plugins: [
react({
jsxImportSource: '#emotion/react',
babel: {
plugins: ['#emotion/babel-plugin'],
},
}),
],
});
And here's my main.js for Storybook:
const svgrPlugin = require('vite-plugin-svgr');
module.exports = {
core: {
builder: 'storybook-builder-vite',
},
stories: ['../src/**/*.stories.mdx', '../src/**/*.stories.#(js|jsx|ts|tsx)'],
addons: ['#storybook/addon-links', '#storybook/addon-essentials'],
viteFinal: (config, { configType }) => {
config.define = {
'window.process': {
env: {
NODE_ENV: configType.toLowerCase(),
},
},
};
return {
...config,
plugins: [
...config.plugins,
svgrPlugin({
svgrOptions: {
icon: true,
},
}),
],
};
},
};
The solution was found in storybook-builder-vite's github page here.

I18next and Webpack

I'm starting with Webpack and find problem with react i18next hook-useTranslation.
// webpack.config.js
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const CopyPlugin = require("copy-webpack-plugin")
module.exports = {
output: {
path: path.join(__dirname, '/dist'),
filename: 'index.bundle.js'
},
devServer: {
port: 3000,
host: 'localhost',
watchContentBase: true,
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /nodeModules/,
use: {
loader: "babel-loader"
}
},
]
},
plugins: [
new HtmlWebpackPlugin(
{
template: './src/index.html'
}
),
new CopyPlugin({
patterns: [
{
from: path.join(__dirname, '/public') , to: path.join(__dirname, '/dist') // copy public folder, which contains locales for i18next
}
]
})
],
}
//i18next.js
import i18next from 'i18next'
import { initReactI18next } from 'react-i18next'
import HttpApi from 'i18next-http-backend'
i18next
.use(initReactI18next)
.use(HttpApi)
.init(
{
backend: {
loadPath: '/locales/{{lng}}/{{ns}}.json'
},
lng: "en_GB",
supportedLngs: ["en_GB","cs_CZ"]
})
export default i18next
//example.js
import React from 'react'
import { useTranslation } from 'react-i18next'
const Greeting = () => {
const { t } = useTranslation()
return (
<div>
{/* {t("common:greeting")} */}
</div>
)
}
export default Greeting
In browser nothing loads and in console print these errors
[WDS] Disconnected!
Uncaught Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons: ...
I want have locales in public folder, not in assets, acording docs, it's better to keep code separated from translations. I tried everything, but I can't find any solution. Someone had a similar problem?
You didnt define a namespace, so loadPath: '/locales/{{lng}}/{{ns}}.json' wont find {{ns}}.json because you said that you have to find {t("common:greeting")}, the namespace that you are searching for is common .So in order to fix this change the loadPath: '/locales/{{lng}}/common.json'

Resources