I'm using Rollup to build a UMD version of my module.
This rollup.config.js successfully builds my module, without including #tensorflow/tfjs:
import path from 'path';
import commonjs from '#rollup/plugin-commonjs';
import { nodeResolve } from '#rollup/plugin-node-resolve';
export default {
input: "dist/tmp/index.js",
output: {
file: "dist/umd/index.js",
format: 'umd',
name: 'Foo',
globals: {
'#tensorflow/tfjs': 'tf',
}
},
context: 'window',
external: ['#tensorflow/tfjs'],
}
However, I rely on a second module (tensor-as-base64) that I do want to include in the bundle. I cannot figure out how to include that specific module.
From a lot of googling it seems like I need to use #rollup/plugin-commonjs and #rollup/plugin-node-resolve, but I can't find any examples for how to scope the includes to a specific folder under node_modules. I've tried something like this:
import commonjs from '#rollup/plugin-commonjs';
import { nodeResolve } from '#rollup/plugin-node-resolve';
export default {
input: "dist/tmp/index.js",
output: {
file: "dist/umd/index.js",
format: 'umd',
name: 'Foo',
globals: {
'#tensorflow/tfjs': 'tf',
}
},
context: 'window',
external: ['#tensorflow/tfjs'],
plugins: [
nodeResolve({
}),
commonjs({
include: [/tensor-as-base64/],
namedExports: {
'tensor-as-base64': ['tensorAsBase64'],
},
}),
]
};
This seems to just hang with no output.
Any tips on how to include a single specific module from the node_modules folder (and ignore everything else in that folder)?
Update 1
I tried this config:
export default {
input: "dist/tmp/index.js",
output: {
file: "dist/umd/index.js",
format: 'umd',
name: 'Foo',
globals: {
'#tensorflow/tfjs': 'tf',
}
},
context: 'window',
external: ['#tensorflow/tfjs'],
plugins: [
nodeResolve({
resolveOnly: [
/^(?!.*(#tensorflow\/tfjs))/,
],
}),
],
})
This produces the following output:
dist/tmp/index.js → dist/umd/index.js...
[!] Error: 'default' is not exported by ../../node_modules/tensor-as-base64/dist/index.js, imported by dist/tmp/upscale.js
Which is accurate in that tensor-as-base64 does not export default.
After including the commonjs plugin, it gets into an infinite loop. I think that's where I'm missing some bit of configuration.
I should add that this is a monorepo, so maybe there's an issue with node_modules being at the root of the folder?
Related
So I was trying to bundle in a bunch of external package dependencies using roll-up, like three JS and deck.gl. Right now I have a rollup config file set up like so, one to build just the code I have written and another that bundles in all the dependencies :
import externals from "rollup-plugin-node-externals";
export default [
{
input: "./Src/index.js",
output: [
{
file: "./Build/pgl.js",
format: "iife",
plugins: [
externals({
deps: true, // Dependencies will not be bundled in
}),
],
},
{
file: "./Build/pgl_module.js",
format: "iife",
plugins: [
externals({
deps: false, // Dependencies will be bundled in
}),
],
sourceMap: true,
},
],
},
];
I have also tried to do the same thing with something like
import { nodeResolve } from '#rollup/plugin-node-resolve';
export default {
input: 'src/index.js',
output: {
dir: 'output',
format: 'cjs'
},
plugins: [nodeResolve()]
};
but to no avail it never bundles up the node packages into the build file and always gives the error :
...
three/examples/jsm/lines/Line2.js (guessing 'Line2_js')
three/examples/jsm/lines/LineMaterial.js (guessing 'LineMaterial_js')
three/examples/jsm/lines/LineGeometry.js (guessing 'LineGeometry_js')
three/examples/jsm/controls/OrbitControls (guessing 'OrbitControls')
#deck.gl/core (guessing 'core')
#deck.gl/layers (guessing 'layers')
(!) Unresolved dependencies
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,
},
};
I've tried several guides and many configurations, but can't get my rollup, postcss, and svelte bundle process to work quite right.
Right now the svelte plugin is extracting the css from my .svelte files and emitting it to the posctcss plugin, but it's doing it one file at a time instead of the entire bundle. This makes it so some functions in the purgecss and nanocss postcss plugins don't completely work because they need the entire bundle to do things like remove duplicate/redundant/unused css rules.
// rollup.config.js
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 rollup_start_dev from './rollup_start_dev'
import builtins from 'rollup-plugin-node-builtins'
import postcss from 'rollup-plugin-postcss'
const production = !process.env.ROLLUP_WATCH
export default {
input: 'src/main.js',
output: {
sourcemap: true,
format: 'iife',
name: 'app',
file: 'public/bundle.js',
},
plugins: [
svelte({
dev: !production,
emitCss: true,
}),
postcss({
extract: true,
sourceMap: true,
}),
builtins(),
resolve({
browser: true,
dedupe: importee =>
importee === 'svelte' || importee.startsWith('svelte/'),
}),
commonjs(),
!production && rollup_start_dev,
!production && livereload('public'),
production && terser(),
],
watch: {
clearScreen: false,
},
}
// postcss.config.js
const production = !process.env.ROLLUP_WATCH
const purgecss = require('#fullhuman/postcss-purgecss')
module.exports = {
plugins: [
require('postcss-import')(),
require('tailwindcss'),
require('autoprefixer'),
production &&
purgecss({
content: ['./src/**/*.svelte', './src/**/*.html', './public/**/*.html'],
css: ['./src/**/*.css'],
whitelistPatterns: [/svelte-/],
defaultExtractor: content => content.match(/[\w-/:]+(?<!:)/g) || [],
}),
production &&
require('cssnano')({
preset: 'default',
}),
],
}
How can I have rollup pass the entire bundle.css to postcss instead of one "file" at a time?
I had the same problem, preprocess goes file by file, so I had to actually include all my mixins and vars in every file, which is absolutely not a good solution.
So for me the first solution was to remove postcss from sveltePreprocess, not emit the css file and to use postcss on the css bundle, that you get in the css function from svelte.
You can then or (1) use postcss directly in the css function of svelte, and then emit the resulting css file in your dist directory, or (2) you can emit this file in a CSS directory, and have postcss-cli watch this directory and bundle everything
Solution 1
// rollup.config.js
// rollup.config.js
import svelte from 'rollup-plugin-svelte';
import resolve from 'rollup-plugin-node-resolve';
import postcss from 'postcss';
import postcssConfig from './postcss.config.js';
const postcssPlugins = postcssConfig({});
const postcssProcessor = postcss(postcssPlugins);
export default {
input: 'src/main.js',
output: {
file: 'public/bundle.js',
format: 'iife',
},
plugins: [
svelte({
emitCss: false,
css: async (css) => {
const result = await postcssProcessor.process(css.code);
css.code = result.css;
css.write('public/bundle.css');
},
}),
resolve(),
],
};
and my postcss.config.js which returns a function that return an array of plugins:
export default (options) => {
const plugins = [
require('postcss-preset-env')()
];
if (options.isProd) {
plugins.push(require('cssnano')({ autoprefixer: false }));
}
return plugins;
};
Solution 2
// rollup.config.js
import svelte from 'rollup-plugin-svelte';
import resolve from 'rollup-plugin-node-resolve';
export default {
input: 'src/main.js',
output: {
file: 'public/bundle.js',
format: 'iife',
},
plugins: [
svelte({
emitCss: false,
css: async (css) => {
css.write('css/svelte-bundle.css');
},
}),
resolve(),
],
};
// package.json
{
//...
"scripts": {
"dev": "npm-run-all --parallel js:watch css:watch",
"js:watch": "rollup -c -w",
"css:watch": "postcss css/app.css --dir dist/ --watch",
},
}
/* css/app.css */
#import 'vars.css';
#import 'mixins.css';
/* all other code ... */
/* and svelte-bundle, which will trigger a bundling with postcss everytime it is emitted */
#import 'svelte-bundle.css';
Conclusion
All in all, I don't like this methods, for exemple because I can't use nesting, as svelte throws an error if the css is not valid.
I would prefer being able to use rollup-plugin-postcss after rollup-plugin-svelte, with emitCss set to false and the possibility to use rollup's this.emitFile in svelte css function, because since once the bundled file is emitted, we should be able to process it.
It seems there are some issues talking about using emitfile, let's hope it will happen sooner than later https://github.com/sveltejs/rollup-plugin-svelte/issues/71
Can't say for sure, but when i compare your setup with mine the most striking difference is that i have:
css: css => {
css.write('public/build/bundle.css');
}
in the svelte options additionally.
My whole svelte option looks like this:
svelte({
preprocess: sveltePreprocess({ postcss: true }),
dev: !production,
css: css => {
css.write('public/build/bundle.css');
}
})
Note, i'm using sveltePreprocess which would make your postcss superfluous, but i don't think that is causing your issue.
I have created an npm library, where I am exploring using rollup for bundling.
Here is the config:
import babel from 'rollup-plugin-babel';
import resolve from 'rollup-plugin-node-resolve';
import commonjs from 'rollup-plugin-commonjs';
import { terser } from 'rollup-plugin-terser';
import { sizeSnapshot } from 'rollup-plugin-size-snapshot';
import pkg from './package.json';
const input = 'src/index.js';
const name = 'TooltipTrigger';
const globals = {
react: 'React',
'react-dom': 'ReactDOM',
'prop-types': 'PropTypes',
'react-popper': 'ReactPopper'
};
const external = id => !id.startsWith('.') && !id.startsWith('/');
const getBabelOptions = ({ useESModules = true } = {}) => ({
exclude: 'node_modules/**',
runtimeHelpers: true,
plugins: [['#babel/plugin-transform-runtime', { useESModules }]]
});
export default [
{
input,
output: {
name,
file: 'dist/react-popper-tooltip.js',
format: 'iife',
globals
},
external: Object.keys(globals),
plugins: [
resolve({
browser: true,
modulesOnly: true
}),
commonjs({
include: 'node_modules/**'
}),
babel(getBabelOptions()),
sizeSnapshot()
]
},
{
input,
output: {
name,
file: 'dist/react-popper-tooltip.min.js',
format: 'iife',
globals
},
external: Object.keys(globals),
plugins: [
resolve({
browser: true,
modulesOnly: true
}),
commonjs({
include: 'node_modules/**'
}),
babel(getBabelOptions()),
terser(),
sizeSnapshot()
]
},
{
input,
output: { file: pkg.main, format: 'cjs' },
external,
plugins: [babel(getBabelOptions({ useESModules: false })), sizeSnapshot()]
},
{
input,
output: { file: pkg.module, format: 'esm' },
external,
plugins: [babel(getBabelOptions()), sizeSnapshot()]
}
];
I want to remove prop types from prod builds in the IIFE build. The babel-plugin-transform-react-remove-prop-types removes the prop types declarations well, but since I have declared prop-types as global in rollup config, it keeps it as a dependency. When I remove it from globals, it resolves the package and bundles it inside the final build. What should I do here? Also is my build config optimal w.r.t. creating iife, cjs and esm builds?
You can use transform-react-remove-prop-types babel plugin with options removeImport: true. So this condition finally remove prop-types from build.
['transform-react-remove-prop-types', { removeImport: true }] for example.