I'm in a Vite/React/TypeScript application and I'm configuring my first test with Vitest.
When I run my Button test (yarn vitest), I get this error:
packages/frontend/src/components/Generic/Button/Button.test.tsx > Button > should render the button
ReferenceError: document is not defined
I understand that Vitest does not work with JSDom. I have tried several things:
KO: Specifying in the vite.config.ts file to use JSDom
OK: Adding a vitest.config.ts file specifying to use JSDom
OK: Adding an annotation (#vitest-environment jsdom) at the top of the test file
I would prefere use the first option (use vite.config.ts) to share only one configuration. Is it possible ?
Note 1 : JSdom i already installed has "devDependencies".
Note 2 : to use vitest.config.ts i should update the script in package.json like that :
"test": "vitest --config ./packages/frontend/vitest.config.ts"
Here are my files:
// vite.config.ts
import { defineConfig } from 'vite'
import react from '#vitejs/plugin-react'
import viteTsConfigPaths from 'vite-tsconfig-paths'
import tailwindcss from 'tailwindcss'
export default defineConfig({
server: {
port: 4200,
host: 'localhost',
},
rollupOption: {
external: ['#internals/components/index']
},
define: {
global: {},
},
plugins: [
react(),
tailwindcss(),
viteTsConfigPaths({
root: '../../',
}),
],
resolve: {
alias: {
// runtimeConfig is a special alias that is used to import the correct config file
'./runtimeConfig': './runtimeConfig.browser',
// public alias
'#publics': `${__dirname}/public`,
// only internals (private) aliases are allowed here
'#internals/components': `${__dirname}/src/components`,
'#internals/features': `${__dirname}/src/features`,
'#internals/hooks': `${__dirname}/src/hooks`,
'#internals/models': `${__dirname}/src/models`,
'#internals/utils': `${__dirname}/src/utils`,
'#internals/types': `${__dirname}/src/types`,
'#internals/styles': `${__dirname}/src/styles`,
'#internals/assets': `${__dirname}/src/assets`,
'#internals/store': `${__dirname}/src/store`,
'#internals/config': `${__dirname}/src/config`,
'#internals/services': `${__dirname}/src/services`,
},
},
test: {
globals: true,
cache: {
dir: '../../node_modules/.vitest',
},
environment: 'jsdom',
include: ['*.tsx', '*.ts', '*.jsx', '*.js'],
},
})
I tried to add a like this vitest.config.ts :
import { defineConfig } from 'vitest/config'
export default defineConfig({
test: {
include: ['*.ts', '*.tsx'], // FIXME
environment: 'jsdom',
},
})
Related
Problem
I have a project let's call it root (based on Preact) that relies on a components package (based on React):
Building it using rollup works fine. When I switch components to use vitejs to build, root fails at runtime with this error:
index.es.js? [sm]:770 Uncaught TypeError: Cannot read properties of undefined (reading 'current')
at jsxDEV (index.es.js? [sm]:770:64)
at jsxWithValidation (index.es.js? [sm]:954:17)
at jsxWithValidationDynamic (index.es.js? [sm]:992:13)
at d.RecipesExplorer [as constructor] (index.es.js? [sm]:1915:33)
at d.O [as render] (index.js:532:14)
at j (index.js:190:14)
at w (children.js:137:3)
at L (index.js:418:4)
at j (index.js:246:20)
at w (children.js:137:3)
I'm not changing anything in root or how it's run. It's built using vitejs as well (in both scenarios).
Rollup config
Here's the rollup.config.js for components (this is the build scenario that works without issue):
// rollup.config.js for components
import { defineConfig } from 'rollup'
import typescript from 'rollup-plugin-typescript2'
import json from '#rollup/plugin-json'
import styles from 'rollup-plugin-styles'
export default defineConfig([
{
input: 'src/index.ts',
output: [
// I don't think we need both of these. Keeping them since we had them for now in webpack
{
dir: 'dist/esm',
format: 'es',
},
{
dir: 'dist/cjs',
format: 'cjs',
},
],
plugins: [typescript({}), json()],
external: ['react', 'react-dom', 'styled-components'],
}
])
Vitejs config
When I switch to using vitejs, this is the vite config:
// vite.config.js for components
import { defineConfig } from 'vite'
import react from '#vitejs/plugin-react'
import { resolve } from 'path'
export default defineConfig({
mode: 'development',
server: {
port: 3000,
open: false,
},
plugins: [react()],
build: {
minify: false,
target: 'modules',
outDir: './dist',
rollupOptions: {
external: ['react', 'react-dom', 'styled-components'],
},
lib: {
entry: resolve(__dirname, './src/index.ts'),
formats: ['cjs', 'es'],
fileName: format => `index.${format}.js`,
},
emptyOutDir: true,
},
})
Package.json snippet
Since vitejs and rollup place files in different directories, I change package.json as well.
For vitejs:
// package.json when configured for vitejs
"name": "components",
...
"exports": {
".": {
"import": "./dist/index.es.js",
"require": "./dist/index.cjs.js"
}
},
"scripts": {
"build": "vite build",
"build:rollup": "rollup -c",
},
...
For rollup:
// package.json when configured for rollup
"name": "components",
...
"exports": {
".": {
"import": "./dist/esm/index.js",
"require": "./dist/cjs/index.js"
}
},
"scripts": {
"build": "vite build",
"build:rollup": "rollup -c",
},
...
Command I'm running & conclusion
When I build components using npm run build (with vite), I get the above error. When I build with npm run build:rollup I get no error.
What am I doing wrong?
Appendix: Root config and package.json
My vitejs config file for root in case that's helpful. Root uses preact and components are built in React.
// vite.config.js for root
import { defineConfig } from 'vite';
import preact from '#preact/preset-vite';
import { resolve } from 'path';
const config = {
RecipeExplorer: {
entry: resolve(__dirname, './src/recipe-explorer.ts'),
fileName: 'recipe-explorer',
},
RecipeList: {
entry: resolve(__dirname, './src/recipe-list.ts'),
fileName: 'recipe-list',
},
RecipeDetailsLegacy: {
entry: resolve(__dirname, './src/recipe-details.ts'),
fileName: 'recipe-details',
},
};
/** IMPORTANT:
* We're using this LIB_NAME env variable so we can create multiple input and output files at build time.
* At the moment this is a work around. Issue is here: https://github.com/vitejs/vite/issues/4530
* Once the above issue gets resolved, we can do away with this workaround.
*/
const currentConfig = config[process.env.LIB_NAME];
if (currentConfig === undefined) {
console.warn(
'LIB_NAME is not defined or is not valid. If you are running a build command LIB_NAME must be specified.',
);
}
// https://vitejs.dev/config/
export default defineConfig({
resolve: {
alias: {
react: 'preact/compat',
'react-dom': 'preact/compat',
'react-dom/test-utils': 'preact/test-utils',
'react/jsx-runtime': 'preact/jsx-runtime',
},
},
plugins: [preact()],
server: {
port: 3010,
host: '0.0.0.0',
},
build: {
outDir: './dist',
lib: {
...currentConfig,
formats: ['cjs', 'es'],
},
emptyOutDir: false,
},
});
I run root using npm run dev which is defined as vite:
// package.json for root
"name": "root",
"scripts": {
"lint": "eslint 'src/**/*.{ts,tsx}'",
"test": "jest",
"dev": "vite",
...
}
...
I want to be able to add classes through styled-jsx which can be nested and have tailwind directives(#apply screen etc.). Right now it's working on imported css files.
Here's my Vite config:
import { defineConfig } from "vite";
import react from "#vitejs/plugin-react";
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
react({
babel: {
parserOpts: {
plugins: [
"styled-jsx/babel",
// {
// plugins: ["styled-jsx-plugin-postcss"],
// },
],
},
},
}),
],
});
As you see plugins: ["styled-jsx-plugin-postcss"] is commented, because it results in an error, but it's essential to use postcss settings.
If somebody interested, here's the postcss.config.cjs(for non Vite it's .js):
module.exports = {
plugins: {
'tailwindcss/nesting': 'postcss-nesting',
'postcss-preset-env': {
stage: 1
},
tailwindcss: {},
autoprefixer: {},
}
}
Is there a way to configure it in Vite.js ( in Next.js it's trivial, so if someone wants to suggest this idea, just don't, it's about Vite!)
Problem:
We've built a UI package using React, Emotion, and Vite. We're consuming it in a Next.js app.
But when we import a component, we get the following ServerError -
TypeError: Cannot read properties of null (reading 'registered')
Seems like the cache object is null on the server.
Even when adding <CacheProvider> to the Next.js app, we still get the same error.
Extra information:
Here's how our vite.config.js loos like -
import { defineConfig } from 'vite';
import react from '#vitejs/plugin-react';
import packageJson from './package.json';
export default defineConfig({
plugins: [
react({
jsxImportSource: '#emotion/react',
babel: {
plugins: ['#emotion/babel-plugin'],
},
}),
],
esbuild: {
jsxInject: "import React from 'react'",
},
build: {
outDir: 'lib',
lib: {
entry: './src/index',
formats: ['esm'],
fileName: (format) => `ui.${format}.js`,
},
rollupOptions: {
// Externalize dependencies that shouldn't be bundled into library
external: [...Object.keys(packageJson.peerDependencies)],
},
},
});
I have a vite project that uses #walletconnect/client. Everything works fine with
npm run dev
but during build (npm run build) I get these errors
error during build:
Error: 'removeHexPrefix' is not exported by node_modules/#walletconnect/encoding/dist/cjs/index.js, imported by node_modules/#walletconnect/utils/dist/esm/ethereum.js
I have tried a few vite configurations from github
1.
optimizeDeps: {
include: ['#walletconnect/*']
},
optimizeDeps: {
exclude: ['#walletconnect/*']
},
3
build: {
commonjsOptions: {exclude: ['#walletconnect*'], include: []},
},
I do not know anything else to do, but if you have come across this issue or something similar. Please let me know how you solved yours.
Thank you.
Had the same issue (I highly suggest you to check it out). Fixed with this config:
import { defineConfig } from "vite";
import { svelte } from "#sveltejs/vite-plugin-svelte";
import { NodeGlobalsPolyfillPlugin } from "#esbuild-plugins/node-globals-polyfill";
import inject from "#rollup/plugin-inject";
import nodePolyfills from "rollup-plugin-polyfill-node";
// https://vitejs.dev/config/
export default defineConfig({
base: "./",
// Node.js global to browser globalThis
define: {
global: "globalThis",
},
plugins: [
svelte(),
inject({
util: "util/",
}),
],
build: {
rollupOptions: {
plugins: [nodePolyfills()],
},
commonjsOptions: {
transformMixedEsModules: true,
},
},
optimizeDeps: {
esbuildOptions: {
// Node.js global to browser globalThis
define: {
global: "globalThis",
},
// Enable esbuild polyfill plugins
plugins: [
NodeGlobalsPolyfillPlugin({
buffer: true,
}),
],same issue
},
},
});```
I am trying to create a ES6 module of a login form using rollup and react-redud.
I have a rollup with the following configuration:
const plugins = [
// Unlike Webpack and Browserify, Rollup doesn't automatically shim Node
// builtins like `process`. This ad-hoc plugin creates a 'virtual module'
// which includes a shim containing just the parts the bundle needs.
{
resolveId(importee) {
if (importee === processShim) return importee;
return null;
},
load(id) {
if (id === processShim) return 'export default { argv: [], env: {} }';
return null;
},
},
nodeResolve(),
commonjs({
include: 'node_modules/**',
namedExports: {
'./node_modules/immutable/dist/immutable.js': ['fromJS', 'Map', 'List', 'Record', 'Iterable'],
'./node_modules/redux/dist/redux.js': ['createStore', 'combineReducers', 'bindActionCreators', 'applyMiddleware', 'compose'],
'./node_modules/react-redux/dist/react-redux.js': [' Provider', 'createProvider', 'connectAdvanced', 'connect'],
},
}),
replace({
'process.env.NODE_ENV': JSON.stringify(prod ? 'production' : 'development'),
}),
inject({
process: processShim,
}),
json(),
babel({
plugins: ['external-helpers'],
exclude: 'node_modules/**',
}),
cleanup(),
];
if (prod) plugins.push(uglify(), visualizer({ filename: './bundle-stats.html' }));
export default {
input: 'src/index.js',
sourcemap: true,
name: pkg.name,
external: ['react', 'react-dom', 'prop-types', 'styled-components', 'bootstrap-styled', 'classnames', 'react-transition-group', 'loaders', 'redux-form', 'redux', 'react-redux', 'react-intl', 'message-common', 'bootstrap-styled-motion'],
exports: 'named',
output,
plugins,
globals: { react: 'React', 'react-dom': 'ReactDom', 'prop-types': 'PropTypes', 'styled-components': 'styled', classnames: 'cn', 'react-transition-group': 'ReactTransitionGroup', loaders: 'loaders', 'redux-form': 'redux-form', 'react-intl': 'react-intl', 'message-common': 'message-common' },
};
My rollup bundle fine, no warnings.
I have tried every possibility of import :
import reduxForm from 'redux-form/lib/immutable/reduxForm';
import Field from 'redux-form/lib/immutable/Field';
and
import { Field, reduxForm } from 'redux-form/es/immutable';
and
import { Field, reduxForm } from 'redux-form/es/immutable';
But nothing work, everytime I install this module somewhere, the transpiled ES replace this line with these imports
import reactRedux from 'react-redux';
import redux from 'redux';
I assume this is happening because redux-form depend on these two. Because these two modules doesn't have default export, this throw an error :
WARNING in ./node_modules/login-form/dist/login-form.es.js
3471:19-24 "export 'default' (imported as 'redux') was not found in 'redux'
WARNING in ./node_modules/login-form/dist/login-form.es.js
3524:26-36 "export 'default' (imported as 'reactRedux') was not found in 'react-redux'
I have tried to play with globals, namedExports. I haven't found a way to make redux-form a peer of my project.
I finally solved it and I had to set my externals with redux-form/immutable instead of just redux-form