We have a react app that we were building using webpack, but are trying to migrate into Vite the significantly lower build times.
We've successfully refactored our build code to use vite, where builds and dev server run successfully when we run them locally. However, whenever we deploy to heroku, and the build script starts... the build simply stalls on the while transforming the js files.
Log Below:
...
2023-02-05T19:26:35.377Z vite:resolve 2.32ms css_variables/colors.css -> /tmp/build_38ed17db/src/css/css_variables/colors.css
2023-02-05T19:26:35.861Z vite:resolve 0.33ms css_variables/durations.css -> /tmp/build_38ed17db/src/css/css_variables/durations.css
2023-02-05T19:26:36.059Z vite:resolve 0.12ms css_variables/sizes.css -> /tmp/build_38ed17db/src/css/css_variables/sizes.css
2023-02-05T19:26:36.090Z vite:resolve 0.12ms css_variables/indices.css -> /tmp/build_38ed17db/src/css/css_variables/indices.css
2023-02-05T19:26:36.175Z vite:resolve 0.22ms index.css -> /tmp/build_38ed17db/src/css/index.css
2023-02-05T19:26:36.210Z vite:resolve 0.12ms nav_bar.css -> /tmp/build_38ed17db/src/css/nav_bar.css
2023-02-05T19:26:36.340Z vite:resolve 0.19ms other_pages/auth_page.css -> /tmp/build_38ed17db/src/css/other_pages/auth_page.css
2023-02-05T19:26:36.460Z vite:resolve 0.37ms other_pages/page.css -> /tmp/build_38ed17db/src/css/other_pages/page.css
2023-02-05T19:26:36.724Z vite:resolve 0.19ms other_pages/simple_pages.css -> /tmp/build_38ed17db/src/css/other_pages/simple_pages.css
2023-02-05T19:26:37.009Z vite:resolve 0.18ms superadmin/superadmin_page.css -> /tmp/build_38ed17db/src/css/superadmin/superadmin_page.css
2023-02-05T19:26:37.133Z vite:resolve 0.16ms other_pages/pricing_calculator_page.css -> /tmp/build_38ed17db/src/css/other_pages/pricing_calculator_page.css
2023-02-05T19:26:37.954Z vite:resolve 0.20ms other_pages/project_portfolio_page.css -> /tmp/build_38ed17db/src/css/other_pages/project_portfolio_page.css
I've been scratching my head for days, because there are no log outputs for an error having occurred, and I've run out of options for searching online for solutions to this problem.
Our config looks as follows:
import { defineConfig, loadEnv } from "vite";
import * as path from "path";
import { fileURLToPath } from "url";
import react from "#vitejs/plugin-react";
import rollupNodePolyFill from "rollup-plugin-polyfill-node";
import { NodeModulesPolyfillPlugin } from "#esbuild-plugins/node-modules-polyfill";
import svgr from "vite-plugin-svgr";
import inject from "#rollup/plugin-inject";
import progress from 'vite-plugin-progress'
import dns from "dns";
dns.setDefaultResultOrder("verbatim");
export default defineConfig(({ command, mode, ssrBuild }) => {
const env = loadEnv(mode, process.cwd(), "");
return {
base: "/",
root: "./",
resolve: {
alias: {
"react-native": "react-native-web",
"src": path.resolve(path.dirname(fileURLToPath(import.meta.url)), "./src"),
util: "rollup-plugin-node-polyfills/polyfills/util",
sys: "util",
events: "rollup-plugin-node-polyfills/polyfills/events",
stream: "rollup-plugin-node-polyfills/polyfills/stream",
path: "rollup-plugin-node-polyfills/polyfills/path",
querystring: "rollup-plugin-node-polyfills/polyfills/qs",
punycode: "rollup-plugin-node-polyfills/polyfills/punycode",
url: "rollup-plugin-node-polyfills/polyfills/url",
string_decoder:
"rollup-plugin-node-polyfills/polyfills/string-decoder",
http: "rollup-plugin-node-polyfills/polyfills/http",
https: "rollup-plugin-node-polyfills/polyfills/http",
os: "rollup-plugin-node-polyfills/polyfills/os",
assert: "rollup-plugin-node-polyfills/polyfills/assert",
constants: "rollup-plugin-node-polyfills/polyfills/constants",
_stream_duplex:
"rollup-plugin-node-polyfills/polyfills/readable-stream/duplex",
_stream_passthrough:
"rollup-plugin-node-polyfills/polyfills/readable-stream/passthrough",
_stream_readable:
"rollup-plugin-node-polyfills/polyfills/readable-stream/readable",
_stream_writable:
"rollup-plugin-node-polyfills/polyfills/readable-stream/writable",
_stream_transform:
"rollup-plugin-node-polyfills/polyfills/readable-stream/transform",
timers: "rollup-plugin-node-polyfills/polyfills/timers",
console: "rollup-plugin-node-polyfills/polyfills/console",
vm: "rollup-plugin-node-polyfills/polyfills/vm",
zlib: "rollup-plugin-node-polyfills/polyfills/zlib",
tty: "rollup-plugin-node-polyfills/polyfills/tty",
domain: "rollup-plugin-node-polyfills/polyfills/domain",
buffer: "rollup-plugin-node-polyfills/polyfills/buffer-es6",
process: "rollup-plugin-node-polyfills/polyfills/process-es6",
"node-modules-polyfills:buffer": "buffer",
"node-modules-polyfills:string_decoder": "string_decoder"
}
},
server: {
port: 3001
},
// Env vars aren't exposed by default so we need to opt-in by prefix
envPrefix: [
"REACT_APP_",
"NODE_ENV"
],
define: {
__APP_ENV__: env.APP_ENV,
"process.env": env,
VITE: true
},
build: {
target: "modules",
minify: "esbuild",
manifest: true,
sourcemap: true,
outDir: "build",
rollupOptions: {
cache: true,
plugins: [
inject({
exclude: ["node_modules/library/**/*.js"]
}),
rollupNodePolyFill()
],
output: {
manualChunks(id) {
if (id.includes('recharts')) {
return 'recharts';
}
}
}
},
commonjsOptions: {
transformMixedEsModules: true,
esmExternals: "auto"
}
},
optimizeDeps: {
esbuildOptions: {
define: {
global: "globalThis"
},
plugins: [
NodeModulesPolyfillPlugin()
]
}
},
plugins: [
react(),
svgr(),
progress()
]
};
});
Our heroku server sets YARN_PRODUCTION to true, and uses the YARN_CACHE but we've attempted removing those to no avail.
I've followed just about every guide to fix this problem I can find online, and it still just wont work.
I'm under the impression that perhaps the build is running out of memory (our application is quite large), but usually when that is the case, heroku would notify us in the logs.
If there is any significant details that would be helpful in attempting to help, please let me know, and I'll do my best to provide them. But I am seriously confused at what is going wrong.
some tips :
this line is only relevant for dev mode server , try to comment it
dns.setDefaultResultOrder("verbatim");
I think the process try to apply polyfills to existing polyfills....
Related
I am trying to bundle my Node.js server-side code (Koa app) into a single file which is what Webpack produces when I use the target as node. This is what ncc - node.js compiler collection also achieves.
I am now using Vite for my next project. I am able to bundle the code by using the SSR bundling feature provided by Vite. But I am not able to bundle third-party dependencies into this single file excluding core/built-in node.js modules. This is my Vite build script:
import path from 'path';
import { build } from 'vite';
import builtinModules from 'builtin-modules';
async function main() {
const result = await build({
mode: 'production',
appType: 'custom',
root: path.join(process.cwd(), 'backend'),
ssr: {
format: 'esm',
target: 'node',
// By default Vite bundles everything except the one we pass via `external` array.
external: builtinModules
},
build: {
manifest: false,
rollupOptions: {
input: 'backend/main.mjs',
output: {
assetFileNames: 'bundle.js'
}
},
outDir: '../dist/backend',
ssr: true,
emptyOutDir: true
},
plugins: [],
});
}
main();
In the above code, builtinModules is simply the string array of all the core node.js modules:
// builtinModules
[
'assert', 'async_hooks',
'buffer', 'child_process',
'cluster', 'console',
'constants', 'crypto',
'dgram', 'diagnostics_channel',
'dns', 'domain',
'events', 'fs',
'http', 'http2',
'https', 'inspector',
'module', 'net',
'os', 'path',
'perf_hooks', 'process',
'punycode', 'querystring',
'readline', 'repl',
'stream', 'string_decoder',
'timers', 'tls',
'trace_events', 'tty',
'url', 'util',
'v8', 'vm',
'worker_threads', 'zlib'
]
For my original source code:
// main.mjs
import path from 'path';
import Koa from 'koa';
async function main() {
console.log('Source folder', path.join(__dirname, 'src'));
const app = new Koa();
app.listen(3000);
}
main();
The produced output for the above Vite build configuration is:
// bundle.js
import path from "path";
import Koa from "koa";
async function main() {
console.log("Source folder", path.join(__dirname, "src"));
const app = new Koa();
app.listen(3e3);
}
main();
Ideally, I expected that it would bundle the koa package in the final output leaving behind only native path module. But that's not the case.
So, how do I enable bundling of my entire backend/Node.js source code compile into single file leaving only core node.js modules as external as Node.js is the runtime for my code? The vite server options also provide the noexternal option but setting it to the true works only for webworker like runtime where none of the built-in node modules are available.
Latest vite versions are using preloading you should tweak some rollup options to disable code splitting
import { defineConfig } from 'vite' // 2.8.0
import react from '#vitejs/plugin-react' // 1.0.7
export default defineConfig ({
plugins: [react()],
build: {
rollupOptions: {
output: {
manualChunks: {}
},
},
},
})
Locally, Vite builds just fine. However, in CI (which just runs the same script, npm run build), it fails.
I get this error in CI:
Error: "Buffer" is not exported by "__vite-browser-external", imported by "src/index.html?html-proxy&index=0.js".
file: /home/runner/work/explorer/explorer/src/index.html?html-proxy&index=0.js:2:13
1:
2: import { Buffer } from "buffer";
^
3: window.Buffer = Buffer;
Error: error during build:
RollupError: "Buffer" is not exported by "__vite-browser-external", imported by "src/index.html?html-proxy&index=0.js".
I added the line that is causing the error because of an issue when running vite serve locally (it errors) - StackOverflow suggested this solution. It builds fine even in CI without that line.
Here's my Vite config:
import { defineConfig } from 'vite'
import react from '#vitejs/plugin-react'
import viteTsconfigPaths from 'vite-tsconfig-paths'
import svgrPlugin from 'vite-plugin-svgr'
import { createHtmlPlugin } from 'vite-plugin-html'
import EnvironmentPlugin from 'vite-plugin-environment'
import { NodeGlobalsPolyfillPlugin } from '#esbuild-plugins/node-globals-polyfill'
export default defineConfig({
root: './src',
envDir: '..',
build: {
// relative to the root
outDir: '../build',
},
// relative to the root
publicDir: '../public',
server: {
open: true,
port: 3000,
proxy: {
'/api': 'http://localhost:5001',
},
},
define: { 'process.env': {} },
resolve: {
alias: {
events: 'events',
stream: 'stream-browserify',
zlib: 'browserify-zlib',
'util/': 'util',
},
},
optimizeDeps: {
esbuildOptions: {
define: {
// Node.js global to browser globalThis
global: 'globalThis',
},
// Enable esbuild polyfill plugins
plugins: [
NodeGlobalsPolyfillPlugin({
buffer: true,
}),
],
},
},
plugins: [
svgrPlugin({
exportAsDefault: true,
}),
react({
// Use React plugin in all *.jsx and *.tsx files
include: '**/*.{jsx,tsx}',
}),
createHtmlPlugin({
inject: {
data: {
VITE_GA_ID: process.env.VITE_GA_ID,
VITE_ZENDESK_KEY: process.env.VITE_ZENDESK_KEY,
},
},
}),
EnvironmentPlugin('all'),
NodeGlobalsPolyfillPlugin({
buffer: true,
process: true,
}),
viteTsconfigPaths(),
],
test: {
globals: true,
setupFiles: 'src/setupTests.js',
},
})
My build command is DISABLE_NEW_JSX_TRANSFORM=true vite build --emptyOutDir
My serve command is DISABLE_NEW_JSX_TRANSFORM=true vite serve
I'm using this github cli plugin to scaffold mv3 chrome extensions using vue and vite.
The template is created correctly and I'm able to work on it, but I have a problem when I want to use the chrome.window.create or chrome.tabs.create, when I run the build command the final folder will not contain the popup.html file, it will be bundled only if is used inside the manifest.js file that is used to generate the build
This is the manifest configuration
import { defineManifest } from '#crxjs/vite-plugin'
export default defineManifest({
name: '',
description: '',
version: '1.0.0',
manifest_version: 3,
icons: {
16: 'img/logo-16.png',
32: 'img/logo-34.png',
48: 'img/logo-48.png',
128: 'img/logo-128.png',
},
//If I uncomment popup will be included but tabs and popup windows will not work
action: {
// default_popup: 'popup.html',
// default_icon: 'img/logo-48.png',
},
//options_page: 'options.html',
background: {
service_worker: 'src/background/index.js',
type: 'module',
},
content_scripts: [
{
matches: ['http://*/*', 'https://*/*'],
js: ['src/content/index.js'],
},
],
host_permissions: [
'https://*.herokuapp.com/*'
],
web_accessible_resources: [
{
resources: ['img/logo-16.png', 'img/logo-34.png', 'img/logo-48.png', 'img/logo-128.png'],
matches: [],
},
],
permissions: [
'tabs',
'gcm',
'identity',
],
oauth2: {
"client_id": "...cd.apps.googleusercontent.com",
"scopes": [
"https://www.googleapis.com/auth/userinfo.email",
"https://www.googleapis.com/auth/userinfo.profile"
]
}
})
And this is the vite code I have
import { defineConfig } from 'vite'
import { crx } from '#crxjs/vite-plugin'
import vue from '#vitejs/plugin-vue'
import manifest from './src/manifest.js'
// https://vitejs.dev/config/
export default defineConfig(({ mode }) => {
const production = mode === 'production'
return {
build: {
emptyOutDir: true,
outDir: 'build',
rollupOptions: {
output: {
chunkFileNames: 'assets/chunk-[hash].js',
},
},
},
plugins: [crx({ manifest }), vue()],
}
})
How I can fix the build to include the popup.html page or any custom html page I can need?
In my Vite project, I am depending on a module that makes use of the process Node global in one of its functions. I don't call this function from my code, but the Vite dev server still gives me this error when I import the module:
Uncaught ReferenceError: process is not defined
Interestingly, I don't see this error when I create a production build.
How can I polyfill process with a no-op so that the Vite dev server stops failing?
An alternative is adding to your index.html
<script type="module">
import process from 'process';
window.process = process;
</script>
I had the same issue today in a React project using rollup + vite and here's how I solved it, using this Medium piece by Fabiano Taioli.
Vite needs Node.js polyfills
You need to add some polyfill plugins to allow Node globals, such as process. Fortunately, you can simply edit (or create) the vite.config.js.
Example vite.config.js
Below is an example which includes using NodeGlobalsPolyfillPlugin to polyfill process. It also includes many other node globals so remove at your leisure.
import { defineConfig } from 'vite';
import { NodeGlobalsPolyfillPlugin } from '#esbuild-plugins/node-globals-polyfill';
import { NodeModulesPolyfillPlugin } from '#esbuild-plugins/node-modules-polyfill';
import ReactPlugin from 'vite-preset-react';
import rollupNodePolyFill from 'rollup-plugin-node-polyfills'
// https://vitejs.dev/config/
export default defineConfig({
resolve: {
alias: {
// This Rollup aliases are extracted from #esbuild-plugins/node-modules-polyfill,
// see https://github.com/remorses/esbuild-plugins/blob/master/node-modules-polyfill/src/polyfills.ts
// process and buffer are excluded because already managed
// by node-globals-polyfill
util: 'rollup-plugin-node-polyfills/polyfills/util',
sys: 'util',
events: 'rollup-plugin-node-polyfills/polyfills/events',
stream: 'rollup-plugin-node-polyfills/polyfills/stream',
path: 'rollup-plugin-node-polyfills/polyfills/path',
querystring: 'rollup-plugin-node-polyfills/polyfills/qs',
punycode: 'rollup-plugin-node-polyfills/polyfills/punycode',
url: 'rollup-plugin-node-polyfills/polyfills/url',
string_decoder: 'rollup-plugin-node-polyfills/polyfills/string-decoder',
http: 'rollup-plugin-node-polyfills/polyfills/http',
https: 'rollup-plugin-node-polyfills/polyfills/http',
os: 'rollup-plugin-node-polyfills/polyfills/os',
assert: 'rollup-plugin-node-polyfills/polyfills/assert',
constants: 'rollup-plugin-node-polyfills/polyfills/constants',
_stream_duplex:
'rollup-plugin-node-polyfills/polyfills/readable-stream/duplex',
_stream_passthrough:
'rollup-plugin-node-polyfills/polyfills/readable-stream/passthrough',
_stream_readable:
'rollup-plugin-node-polyfills/polyfills/readable-stream/readable',
_stream_writable:
'rollup-plugin-node-polyfills/polyfills/readable-stream/writable',
_stream_transform:
'rollup-plugin-node-polyfills/polyfills/readable-stream/transform',
timers: 'rollup-plugin-node-polyfills/polyfills/timers',
console: 'rollup-plugin-node-polyfills/polyfills/console',
vm: 'rollup-plugin-node-polyfills/polyfills/vm',
zlib: 'rollup-plugin-node-polyfills/polyfills/zlib',
tty: 'rollup-plugin-node-polyfills/polyfills/tty',
domain: 'rollup-plugin-node-polyfills/polyfills/domain',
},
},
optimizeDeps: {
esbuildOptions: {
// Node.js global to browser globalThis
define: {
global: 'globalThis',
},
// Enable esbuild polyfill plugins
plugins: [
NodeGlobalsPolyfillPlugin({
process: true,
buffer: true,
}),
NodeModulesPolyfillPlugin(),
],
},
},
plugins: [
ReactPlugin({
injectReact: false,
}),
rollupNodePolyFill(),
],
});
Development dependencies required
To make the above example work as is you'll need to add some dependencies. In particular:
yarn add --dev vite-preset-react
yarn add --dev #esbuild-plugins/node-modules-polyfill
yarn add --dev #esbuild-plugins/node-globals-polyfill
I'm using node-stdlib-browser, and it works really well for me.
And the following is my final vite.config.ts
import { defineConfig } from 'vite'
import vue from '#vitejs/plugin-vue'
import path from 'path'
import nodeStdlibBrowser from 'node-stdlib-browser'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import inject from '#rollup/plugin-inject'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
// https://github.com/antfu/unplugin-auto-import#configuration
AutoImport({
dts: 'src/auto-import.d.ts',
imports: ['vue', 'vue-router'],
eslintrc: {
enabled: true,
},
}),
// https://github.com/antfu/unplugin-vue-components#configuration
Components({
dts: 'src/components.d.ts',
}),
// https://github.com/niksy/node-stdlib-browser#vite
{
...inject({
global: [require.resolve('node-stdlib-browser/helpers/esbuild/shim'), 'global'],
process: [require.resolve('node-stdlib-browser/helpers/esbuild/shim'), 'process'],
Buffer: [require.resolve('node-stdlib-browser/helpers/esbuild/shim'), 'Buffer'],
}),
enforce: 'post',
},
],
resolve: {
alias: { '#': path.resolve(__dirname, 'src'), ...nodeStdlibBrowser },
},
optimizeDeps: {
esbuildOptions: {
target: 'esnext', // Enable Big integer literals
},
},
build: {
target: 'esnext', // Enable Big integer literals
commonjsOptions: {
transformMixedEsModules: true, // Enable #walletconnect/web3-provider which has some code in CommonJS
},
},
})
I'm trying to use a package: quoters
this is app.svelte file. the same code works fine for react and other places in JS.
<script>
import Quote from "quoters";
let quote = "";
let category = "QUOTE";
function handleCategory() {
quote = new Quote(category).get();
}
</script>
when I am trying to run the code. i get the following error: "Uncaught ReferenceError: exports is not defined". I checked the line it is referencing to.
it contains definition for exports inside the quoters package.
Object.defineProperty(exports, "__esModule", { value: true });
I've tried everything like babel and commonjs. maybe i am missing something. please can anyone tell me what is the issue and also fix for this issue.
my rollup config file for reference:
import svelte from "rollup-plugin-svelte";
import commonjs from "#rollup/plugin-commonjs";
import resolve from "#rollup/plugin-node-resolve";
import livereload from "rollup-plugin-livereload";
import { terser } from "rollup-plugin-terser";
import css from "rollup-plugin-css-only";
import copy from "rollup-plugin-copy";
import json from "#rollup/plugin-json";
import builtins from "rollup-plugin-node-builtins";
import globals from "rollup-plugin-node-globals";
import replace from "#rollup/plugin-replace";
import babel from "#rollup/plugin-babel";
import nodePolyfills from "rollup-plugin-node-polyfills";
const production = !process.env.ROLLUP_WATCH;
function serve() {
let server;
function toExit() {
if (server) server.kill(0);
}
return {
writeBundle() {
if (server) return;
server = require("child_process").spawn(
"npm",
["run", "start", "--", "--dev"],
{
stdio: ["ignore", "inherit", "inherit"],
shell: true,
}
);
process.on("SIGTERM", toExit);
process.on("exit", toExit);
},
};
}
export default {
input: "src/main.js",
output: {
sourcemap: true,
format: "iife",
name: "app",
file: "public/build/bundle.js",
exports: "auto",
},
moduleContext: {
"node_modules/quoters/dist/parseData.js": "window",
},
plugins: [
svelte({
compilerOptions: {
// enable run-time checks when not in production
dev: !production,
},
}),
nodePolyfills(),
json(),
copy({
targets: [
{
src: "node_modules/bootstrap/dist/**/*",
dest: "public/vendor/bootstrap",
},
],
}),
// we'll extract any component CSS out into
// a separate file - better for performance
css({ output: "bundle.css" }),
// If you have external dependencies installed from
// npm, you'll most likely need these plugins. In
// some cases you'll need additional configuration -
// consult the documentation for details:
// https://github.com/rollup/plugins/tree/master/packages/commonjs
babel({
exclude: "node_modules/**", // only transpile our source code
}),
resolve({
dedupe: ["svelte"],
browser: true,
preferBuiltins: false,
}),
commonjs(),
// In dev mode, call `npm run start` once
// the bundle has been generated
!production && serve(),
// Watch the `public` directory and refresh the
// browser on changes when not in production
!production && livereload("public"),
// If we're building for production (npm run build
// instead of npm run dev), minify
production && terser(),
],
watch: {
clearScreen: false,
},
};