'Buffer' is not exported by __vite-browser-external:buffer - javascript

I'm getting this build error with vite and sveltekit using adapter-node
I'm not sure why it won't build since it relies on node to server the client.
dev works fine
'Buffer' is not exported by __vite-browser-external:buffer
I tried polyfills but they don't work.
optimizeDeps: {
esbuildOptions: {
// Node.js global to browser globalThis
define: {
global: 'globalThis'
},
// Enable esbuild polyfill plugins
plugins: [
NodeGlobalsPolyfillPlugin({
process: true,
buffer: true,
webworkers: true,
}),
NodeModulesPolyfillPlugin()
]
}
},
build: {
minify: true,
rollupOptions: {
plugins: [
// Enable rollup polyfills plugin
// used during production bundling
rollupNodePolyFill()
]
}
}

I solved it by adding the right aliases (including buffer and process) to config.vite.ts. That's how mine looks like:
import { defineConfig } from "vite";
import react from "#vitejs/plugin-react";
import tsconfigPaths from 'vite-tsconfig-paths'
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: [react(), tsconfigPaths()],
server: {
port: 3001,
open: true
},
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
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'
}
},
optimizeDeps: {
esbuildOptions: {
// Node.js global to browser globalThis
define: {
global: 'globalThis'
},
// Enable esbuild polyfill plugins
plugins: [
NodeGlobalsPolyfillPlugin({
process: true,
buffer: true
}),
NodeModulesPolyfillPlugin()
]
}
},
build: {
rollupOptions: {
plugins: [
// Enable rollup polyfills plugin
// used during production bundling
// #ts-ignore
rollupNodePolyFill(),
]
}
}
})

build: {
rollupOptions: {
plugins: [inject({ Buffer: ['Buffer', 'Buffer'] })],
},
},
This works with npm i -D buffer

Related

How to Polyfill node core modules using vite

It seems that vite does not do automatic polyfills anymore - vite 4.0.0
How do you guys go about this? I have tried multiple variations of what I could find over the internet and none of them seems to be solid.
✘ [ERROR] The injected path "/Users/marian/code/OzoneV2/app-web/node_modules/#esbuild-plugins/node-globals-polyfill/_buffer.js" cannot be marked as external
✘ [ERROR] The injected path "/Users/marian/code/OzoneV2/app-web/node_modules/#esbuild-plugins/node-globals-polyfill/_virtual-process-polyfill_.js" cannot be marked as external
Build failed with 2 errors:
error: The injected path "/Users/marian/code/OzoneV2/app-web/node_modules/#esbuild-plugins/node-globals-polyfill/_buffer.js" cannot be marked as external
error: The injected path "/Users/marian/code/OzoneV2/app-web/node_modules/#esbuild-plugins/node-globals-polyfill/_virtual-process-polyfill_.js" cannot be marked as external
my config
// yarn add --dev #esbuild-plugins/node-globals-polyfill
import { NodeGlobalsPolyfillPlugin } from "#esbuild-plugins/node-globals-polyfill";
// yarn add --dev #esbuild-plugins/node-modules-polyfill
import { NodeModulesPolyfillPlugin } from "#esbuild-plugins/node-modules-polyfill";
// You don't need to add this to deps, it's included by #esbuild-plugins/node-modules-polyfill
import rollupNodePolyFill from "rollup-plugin-node-polyfills";
export default {
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(),
],
},
},
build: {
rollupOptions: {
plugins: [
// Enable rollup polyfills plugin
// used during production bundling
rollupNodePolyFill(),
],
},
},
};
I encountered the same issue "cannot be marked as external" when working with the bip39 package and getting error because of buffer not defined. I tried many stuffs so not sure how what I solved, but here is my configuration (working with svelteKit):
In vite.config.js:
import { sveltekit } from '#sveltejs/kit/vite';
import type { UserConfig } from 'vite';
const config: UserConfig = {
plugins: [sveltekit()],
resolve: {
alias: {
// polyfills
Buffer: 'vite-compatible-readable-buffer',
stream: 'vite-compatible-readable-stream',
util: 'rollup-plugin-node-polyfills/polyfills/util',
}
}
};
export default config;
In layout.ts:
import { Buffer as BufferPolyfill } from 'buffer'
declare var Buffer: typeof BufferPolyfill;
globalThis.Buffer = BufferPolyfill
In app.html:
<script>
/**
* this is a hack for error: global is not defined
*/
var global = global || window
</script>
I hope it helps. I'm new to svelte and I don't 100% know what I'm doing :p

Electron application is missing some files only when installing the ".exe" file

I'm building an Electron application with these versions:
electron - 22.0.0
electron-builder - 23.6.0
async npm package - 3.2.4
This is my electron-builder configuration file:
module.exports = {
appId: 'com.electron.balbdldldld',
productName: 'Hblalalala',
files: ['./dist'],
directories: {
buildResources: 'resources',
output: 'release',
},
asarUnpack: '**\\*.{node,dll,exe}',
extraResources: ['build/', 'resources/'],
win: {
target: ['nsis'],
sign: 'scripts/sign.js',
signingHashAlgorithms: ['sha256'],
},
nsis: {
guid: 'bbbbbbb',
include: 'build/installer.nsh',
artifactName: 'blalflflvl.${ext}',
runAfterFinish: false,
createStartMenuShortcut: false,
createDesktopShortcut: false,
},
};
I build the renderer process using vite:
import path from 'path';
import react from '#vitejs/plugin-react';
import { defineConfig } from 'vite';
import tsconfigPaths from 'vite-tsconfig-paths';
import sassDts from 'vite-plugin-sass-dts';
import { version } from './package.json';
export default defineConfig(() => ({
root: path.join(__dirname, 'app', 'renderer'),
server: {
port: 4200,
open: true,
},
base: './',
build: { outDir: path.join(__dirname, 'dist') },
plugins: [react(), tsconfigPaths(), sassDts()],
resolve: { alias: { '#/styles': path.join(__dirname, 'app', 'renderer', 'styles') } },
define: {
__PACKAGE_VERSION__: JSON.stringify(version),
},
}));
And I build the main process using webpack:
import path from 'path';
import webpack from 'webpack';
import nodeExternals from 'webpack-node-externals';
import TsconfigPathsPlugin from 'tsconfig-paths-webpack-plugin';
import TerserPlugin from 'terser-webpack-plugin';
/**
* The function returns the OS target for compilation
* #returns the OS target
*/
const getOsTarget = () => {
if (process.platform === 'win32') {
return 'windows';
}
if (process.platform === 'darwin') {
return 'darwin';
}
return null;
};
const osTarget = getOsTarget();
if (osTarget === null) {
console.log('Failed to build, unsupported platform');
process.exit(1);
}
const rootPath = path.join(__dirname, '..');
const applicationCodePath = path.join(rootPath, 'app');
const distPath = path.join(rootPath, 'dist');
const nodeModulesPath = path.join(rootPath, 'node_modules');
const configuration: webpack.Configuration = {
mode: 'production',
plugins: [
new webpack.EnvironmentPlugin({
NODE_ENV: 'production',
}),
],
target: 'electron-main',
entry: {
main: path.join(applicationCodePath, 'main', 'main.ts'),
preload: path.join(applicationCodePath, 'preload', 'main.ts'),
},
externals: [nodeExternals({ modulesDir: path.join(rootPath, 'node_modules') })],
output: {
path: distPath,
filename: '[name].js',
library: { type: 'umd' },
},
module: {
rules: [
{
test: /\.ts$/,
exclude: /node_modules/,
use: [
{
loader: 'ts-loader',
options: {
configFile: path.join(rootPath, 'tsconfig.build.json'),
transpileOnly: true,
},
},
],
},
],
},
resolve: {
extensions: ['.js', '.json', '.ts'],
modules: [applicationCodePath, nodeModulesPath],
plugins: [
new TsconfigPathsPlugin({
configFile: path.join(rootPath, 'tsconfig.build.json'),
extensions: ['.ts'],
}),
],
},
optimization: {
minimizer: [
new TerserPlugin({
parallel: true,
}),
],
},
plugins: [
new webpack.NormalModuleReplacementPlugin(/\-\[(darwin|windows)\]./, (resource) => {
resource.request = resource.request.replace(/(darwin|windows)/, osTarget);
}),
],
node: {
__dirname: false,
__filename: false,
},
};
export default configuration;
Then I build my complete electron application by running:
Build renderer process code: vite build -c ./vite.config.ts
Build main process code: webpack --config ./webpack/webpack.config.prod.ts
Build electron: electron-builder --config ./electron.build.cjs
Then everything goes fine. When I inspect the results in my release folder I can see this file: ./release/win-unpacked/resources/app.asar. When I unpack it using npx asar unpack app.asar app.unpack I can inspect the app.asar file. Then I can see the following file exists: ./app.unpack/node_modules/async/apply.js. Note that apply.js file. However, when I download the application by using the .exe file, I get a run time error in JS Code:
Uncaught exception:
Error: Cannot find module './apply`
Require Stack:
"........./resources/app.asar/node_modules/async/index.js"
And when I unpack, again with same way, this .../resources/app.asar file, the file indeed does not exist. So why this file is missing while installing the .exe file?
I want this file to exist

`vite build` is throwing `Could not resolve "../internals/window" from "../internals/window?commonjs-external"`

I have recently migrated from CRA to Vite. Everything went smooth, yet the build script is throwing an error.
Seems to be a RollupError
Could not resolve "../internals/window" from "../internals/window?commonjs-external"
When I remove the define object from my config, the build succeeds yet the dev server stops working
I am using the vite 4
here is my config
import { defineConfig } from "vite";
import react from "#vitejs/plugin-react";
import viteTsconfigPaths from "vite-tsconfig-paths";
import svgrPlugin from "vite-plugin-svgr";
// https://vitejs.dev/config/
export default defineConfig(({ command, mode }) => {
return {
plugins: [react(), viteTsconfigPaths(), svgrPlugin()],
preview: {
port: 3000,
},
build: {
outDir: "build",
rollupOptions: {
external: ["jss-plugin-window"],
},
},
define: {
global: "window"
},
server: {
open: true,
port: 3000,
},
envPrefix: "REACT_APP_",
};
});
I use the following the bypass the issue, got the solution from here: https://dev.to/lico/issues-that-i-encountered-and-how-to-deal-with-them-while-migrating-from-cra-to-vite-51pg
define: {
...(process.env.NODE_ENV === 'development' ? {global: 'window'} : {})
}

Vue 3, vite vue.esm-bundler.js build breaks jQuery

So I'm using vite to build my Vue 3 application for a legacy website which still uses jQuery and a few other JS frameworks.
I'm using the esm bundler as I would still like to boot it up and use it with slotted components.
<div id="app">
<vue-component-name></vue-component-name>
</div>
And it works perfectly. But when jQuery is used on the page, no where near my components it seems the esm bundled version of Vue has set a global variable named $ which breaks jQuery.
Has anyone had this issue or know of a way to fix it?
import { defineConfig } from 'vite';
import type { UserConfig as VitestUserConfigInterface } from 'vitest/config';
import svgLoader from 'vite-svg-loader';
import vue from '#vitejs/plugin-vue';
import path from 'path';
const vitestConfig : VitestUserConfigInterface = {
test: {
globals: true,
include: ['./tests/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
},
};
export default defineConfig({
test: vitestConfig.test,
plugins: [vue(), svgLoader()],
base: '/',
resolve: {
alias: {
vue: 'vue/dist/vue.esm-bundler.js',
'#': path.resolve(__dirname, '/src'),
},
},
build: {
outDir: '../wwwroot/dist',
emptyOutDir: true,
manifest: true,
rollupOptions: {
input: {
main: './src/main.ts',
},
output: {
entryFileNames: 'assets/js/[name].js',
chunkFileNames: 'assets/js/[name].js',
assetFileNames: ({ name }) => {
if (/\.(gif|jpe?g|png|svg)$/.test(name ?? '')) {
return 'assets/images/[name][extname]';
}
if ((name ?? '').endsWith('.css')) {
return 'assets/css/[name][extname]';
}
return 'assets/[name][extname]';
},
globals: {
vue: 'Vue',
},
},
},
},
server: {
hmr: {
protocol: 'ws',
},
},
});
EDIT:
More information, I've tracked this down to using
#input="handleInput($event.target, index)"
This right here breaks existing jQuery. Still no idea how to get around it
For anyone interested, How to wrap Vite build in IIFE and still have all the dependencies bundled into a single file?

Rollup is not generating typescript sourcemap

I am using rollup with svelte + typescript + scss. My problem is that I am not able to generate source maps.
Following is my rollup config file:
import svelte from 'rollup-plugin-svelte'
import resolve from '#rollup/plugin-node-resolve'
import commonjs from '#rollup/plugin-commonjs'
import livereload from 'rollup-plugin-livereload'
import { terser } from 'rollup-plugin-terser'
import typescript from '#rollup/plugin-typescript'
import alias from '#rollup/plugin-alias'
const production = !process.env.ROLLUP_WATCH
const path = require('path').resolve(__dirname, 'src')
const svelteOptions = require('./svelte.config')
function serve() {
let server
function toExit() {
if (server) server.kill(0)
}
return {
writeBundle() {
if (server) return
server = require('child_process').spawn(
'yarn',
['run', 'start', '--', '--dev'],
{
stdio: ['ignore', 'inherit', 'inherit'],
shell: true,
}
)
process.on('SIGTERM', toExit)
process.on('exit', toExit)
},
}
}
export default {
input: 'src/main.ts',
output: {
sourcemap: true,
format: 'iife',
name: 'app',
file: 'public/build/bundle.js',
},
plugins: [
alias({
entries: [
{ find: '#app', replacement: `${path}` },
{ find: '#components', replacement: `${path}/components` },
{ find: '#includes', replacement: `${path}/includes` },
{ find: '#styles', replacement: `${path}/styles` },
{ find: '#pages', replacement: `${path}/pages` },
],
}),
svelte(svelteOptions),
// 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
resolve({
browser: true,
dedupe: ['svelte'],
}),
commonjs(),
typescript({ sourceMap: !production }),
// 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,
},
}
I am not sure what exactly am I doing wrong. Here is the link to code I am using.
Any help will be deeply appreciated!
This is what worked for me: you need to set sourceMap: false in the typescript rollup plugin options.
export default {
input: 'src/main.ts',
output: {
sourcemap: true,
format: 'iife',
...
},
plugins: [
...
svelte(...),
typescript({ sourceMap: false }),
...
]
}
It turns out rollup's sourcemap collapser conflicts with the typescript's plugin sourcemap generator. That's why it works on prod builds but not in dev builds (because originally it is sourceMap: !production). Just let rollup do the heavy lifting.
As also mentioned by others, it seems like the combination of TypeScript and Rollup leads to the problem. Disabling the source map in TypeScript only fixes the problem of mapping Svelte to TypeScript. However you only receive a source map showing source in the compiled JavaScript, not in the original TypeScript. I finally found a solution, that worked for me: Just add the Option inlineSources: true to the TypeScript options:
typescript({ sourceMap: !production, inlineSources: !production }),
This circumvents the problem by simply not creating a duplicate SourceMap, but by copying the source code from TypeScript into the SourceMap.
For anyone using terser, not svelte, this solved the same problem for me:
import sourcemaps from 'rollup-plugin-sourcemaps';
import { terser } from 'rollup-plugin-terser';
import typescript from '#rollup/plugin-typescript';
export default [
{
input: 'dist/index.js',
output: [
{
file: 'dist/cjs/index.js',
format: 'cjs'
},
{
file: 'dist/fesm2015/index.js',
format: 'es'
}
],
plugins: [
sourcemaps(),
terser(),
typescript({ sourceMap: true, inlineSources: true })
]
}
];
Apparently rollup-plugin-sourcemaps is needed to do the magic necessary to utilize the map files generated by the TypeScript compiler and feed them to terser.
For me, I am able to map, by making sourcemap: "inline"
In the /build/index.esm.js file will have mapping inside.
export default {
input: "src/index.ts",
output: [
{
file: 'build/index.esm.js',
format: 'es',
sourcemap: "inline"
},
],
plugins: [
typescript({ sourceMap: false, inlineSources: true }),
]
}
I was having a similar issue with Karma, rollup, and typescript. I fixed it by adding "sourceRoot":"/base/" to my tsconfig.json file.
Before: map file entries pointed to /src/.
After: map file entries pointed to /base/src/ and everything worked.
// tsconfig.rollup.json
"compilerOptions": {
"module": "ES2022",
"esModuleInterop": true,
"target": "ES2022",
"moduleResolution": "classic",
"sourceMap": true,
"sourceRoot": "/base/"
...
}
// rollup.config.js
import typescript from '#rollup/plugin-typescript';
export default [
{
input: './src/test/test_context.spec.ts',
output: {
file: './dist/test/test_context.spec.js',
format: 'es',
sourcemap: 'inline'
},
plugins: [
typescript({
tsconfig: './tsconfig.rollup.json'
})
]
}
];

Categories