I followed the steps on the website 'https://angular.io/guide/aot-compiler' to adapt an Angular 2 app to use AoT compilation and everything seemed to work as expected until the rollup step, which in theory cleans up the code of unused components.
Leaving the 'rollup-config.js' file the same as in the instructions, when I run 'node_modules/.bin/rollup -c rollup-config.js' I get the following error:
[!] Error: 'ToastModule' is not exported by node_modules/ng2-toastr/ng2-toastr.js
I've googled it, and I came across a solution that pointed to add a 'namedExports' field to the 'commonjs' parameter. The resulting 'rollup-config.js' is:
import nodeResolve from 'rollup-plugin-node-resolve';
import commonjs from 'rollup-plugin-commonjs';
import uglify from 'rollup-plugin-uglify';
export default {
entry: 'src/main.js',
dest: 'src/build.js',
sourceMap: false,
format: 'iife',
onwarn: function(warning) {
if(warning.code === 'THIS_IS_UNDEFINED') { return; }
console.warn(warning.message);
},
plugins: [
nodeResolve({jsnext: true, module: true}),
commonjs({
include: 'node_modules/**',
namedExports: {
'node_modules/ng2-toastr/ng2-toastr': [ 'ToastModule' ]
}
}),
uglify()
]
}
Now, the script generates the 'build.js' file and I can load it through the index.html file, but the component 'ng2-toastr' is not working (the component shows a 'toast' like message, appearing on one side of the screen and disappearing after a few seconds).
Did I miss something? Thanks in advance,
Related
I am trying to make a library/package from my component.
Tech-stack is: React, Typescript... and a bunch of other dependencies.
I am using Rollup and when I try to build the package I get the following error:
[!] Error: 'DisplayHint' is not exported by
../node_modules/#bestowinc/enroll-sdk-core/build/lib/question-common.js,
imported by ../src/utils/answerTypeConversions.ts
https://rollupjs.org/guide/en/#error-name-is-not-exported-by-module
Rollup:
import babel from 'rollup-plugin-babel';
import resolve from '#rollup/plugin-node-resolve';
import external from 'rollup-plugin-peer-deps-external';
import { terser } from 'rollup-plugin-terser';
import postcss from 'rollup-plugin-postcss';
import reactSvg from 'rollup-plugin-react-svg';
import typescript from 'rollup-plugin-typescript2';
import svg from 'rollup-plugin-svg';
import commonjs from '#rollup/plugin-commonjs';
import json from '#rollup/plugin-json';
import replace from '#rollup/plugin-replace';
import urlResolve from 'rollup-plugin-url-resolve';
export default [
{
input: './src/index.ts',
output: [
{
file: './dist/index.js',
format: 'cjs',
sourcemap: true,
},
{
file: './dist/index.es.ts',
format: 'es',
exports: 'named',
sourcemap: true,
},
],
plugins: [
typescript({
tsconfig: './tsconfig.build.json',
verbosity: 3,
clean: true,
check: true,
}),
babel({
exclude: ['/node_modules'],
presets: [
'#babel/preset-react',
'#babel/preset-flow',
'#babel/preset-env',
],
extensions: ['.ts', '.tsx'],
}),
commonjs({
include: './node_modules',
dynamicRequireTargets: [
// include using a glob pattern (either a string or an array of strings)
'/node_modules/#bestowinc/enroll-sdk-core/build/lib/question-common.js',
'./node_modules/#bestowinc/enroll-sdk-core/build/lib/question-common.js',
],
}),
resolve({
browser: true,
preferBuiltins: true,
mainFields: ['browser'],
}),
urlResolve(),
postcss({
plugins: [],
minimize: true,
}),
external(),
terser(),
reactSvg({
jsx: false,
include: ['custom.d.ts'],
exclude: null,
}),
svg(),
replace({
include: ['../src/icons/**'],
preventAssignment: true,
// Replace ReactComponent to allow resolution of SVG files under Rollup
ReactComponent: 'default',
}),
json(),
],
},
];
DisplayHint:
/**
* An indication of how clients should display a question.
*
* This is inferred from the answer_format and answer_display api properties.
* Those properties should not be used directly, and clients should rely instead
* solely on DisplayHint.
*/
export declare const DisplayHint: {
readonly ButtonGroup: "DisplayHint::ButtonGroup";
readonly Checkbox: "DisplayHint::Checkbox";
};
export declare type DisplayHint = typeof DisplayHint[keyof typeof DisplayHint];
Looks like DisplayHint is a TS type/interface, not an exported JS value.
Rollup per se is a bundler not a TS language analyzer. It cannot tell if a named export is a concrete JS value or merely a non-existing TS type, thus the reported error.
Rollup plugin order matters. To resolve this specific problem, just lift the typescript plugin up in order, at least before babel. TS plugin, if put to work first, will correctly erase TS type from JS code output.
Update
I know another trick, but it’s a workaround-ish one. The trick is to use import type syntax to explicitly mark DisplayHint as a TS type.
import type { DisplayHint } from "#bestowinc/enroll-sdk-core"
import { otherNonTypeStuff } from "#bestowinc/enroll-sdk-core"
This trick is not satisfying because it requires you to explicitly mark everywhere you need a TS type, and you have to separate concrete JS exports from TS type ones, like shown above. This is fine if it’s a one-off thing but if you have a large codebase it’s very tedious.
I have to add, it’s unexpected to me that original solution doesn’t work. My guess is that this module #bestowinc/enroll-sdk-core is somehow quirky. (Why you include them as dynamic import target in the config anyway?)
It’s a JS module with .d.ts annotation, that I can tell, but looks like it’s a private module, I cannot see the code thus cannot dive deeper. My guess is that .d.ts declaration is broken, it doesn’t match up to the real export of JS code.
Anyway, I hope this trick resolve your problem. If you need me to look closer, I’ll have to ask you to setup a minimal reproducible example. With current info there’s not much I can do.
I've had similar issue just happening with linked library (with typescript plugin in place), in my case solution was to add the linked library to config 'external' property. But node_modules should be treated as external anyway so not sure if this will apply
I found a plugin rollup-plugin-multi-input which fixes the problem of not being able to specifiy a glob to the test rollup config. For the unt tests, the entry point is not a single entity from which an import graph can be derived. It is just a collection of source files containing tests, which doesnt fit input requirement of rollup.
However, my attempt at trying to use it was fruitless:
rollup-config.tests.mjs:
import multi from 'rollup-plugin-multi-input';
const testConfig = {
input: ['test/**/*.spec.ts'],
external: ["chai", "mocha", "dirty-chai"],
output: {
format: "es",
file: `dist/${name}-bundle.test.js`,
plugins: [],
sourcemap: true
},
plugins: [
multi(),
resolve(),
commonjs(),
typescript({
tsconfig: "./tsconfig.test.json"
})
],
}
just resulted in this error:
[!] TypeError: multi is not a function
TypeError: multi is not a function
Looking at the exported code from the plugin, I can see that the default export is a function:
var _default = function(param) {
}
exports.default = _default;
So I don't know why this doesnt work.
I since discovered that there is another plugin that does a similar thing: #rollup/plugin-multi-entry:
import entry from "rollup-plugin-multi-entry";
plugins: [
entry(),
resolve(),
commonjs(),
typescript({
tsconfig: "./tsconfig.test.json"
})
],
so configured and invoked in exactly the same way, but now it works in the way that I wanted it to; the test bundle is created and mocha indeed sees all the tests and executes them successfully.
So let's take a look at that export and see if there is a difference in what is exported:
Well the first thing to notice is that its dist folder contains a .mjs file and a .js file. Since we're importing from an ESM package ("type": "module" in package.json), I guess we're using the default export from the .mjs file:
function multiEntry() {
...
}
export default multiEntry;
With rollup-plugin-multi-input, I even tried using the createRequire from "module":
import { createRequire } from "module";
const require = createRequire(import.meta.url);
const multi = require('rollup-plugin-multi-input');
but that failed for the same reason.
So whats the problem here? Why does default import from rollup-plugin-multi-input not work?
I'm having a devil of a time figuring out how to build a single .js file from Vite in my Svelte project that includes all of the built javascript and CSS from my Svelte projects. By default, Vite bundles the app into one html file (this is ok), two .js files (why??), and one .css file (just want this bundled into the one js file).
I ran this very basic command to get a starter project:
npx degit sveltejs/template myproject
I tried adding a couple of plugins, but nothing I added achieved the results I wanted. Primarily, the plugins I found seem to want to create a single HTML file with everything in it. It seems like PostCSS might be able to help, but I don't understand what configuration I can set via Vite to get it to do what I want.
What is the magic set of plugins and config that will output a single HTML file with a single js file that renders my Svelte app and its CSS onto the page?
Two steps,
We can inject css into js assets with vite-plugin-css-injected-by-js.
We can emit a single js asset by disabling chunks in rollup's config.
Final result,
import cssInjectedByJsPlugin from "vite-plugin-css-injected-by-js";
export default defineConfig({
plugins: [cssInjectedByJsPlugin()],
build: {
rollupOptions: {
output: {
manualChunks: undefined,
},
},
},
});
If you're looking for a solution to this, you might want to take a look at vite-plugin-singlefile.
That doesn't come out of the box for vite but you can write a quick plugin which will be doing exactly that
const bundle_filename = ''
const css_filename = 'style.css'
defineConfig({
build: {
lib: {
entry: 'src/mycomponent.js',
name: 'mycomponent.js',
fileName: () => 'mycomponent.js',
formats: ['iife'],
},
cssCodeSplit: false,
rollupOptions: {
plugins: [
{
apply: 'build',
enforce: 'post',
name: 'pack-css',
generateBundle(opts, bundle) {
const {
[css_filename]: { source: rawCss },
[bundle_filename]: component,
} = bundle
const IIFEcss = `
(function() {
try {
var elementStyle = document.createElement('style');
elementStyle.innerText = ${JSON.stringify(rawCss)}
document.head.appendChild(elementStyle)
} catch(error) {
console.error(error, 'unable to concat style inside the bundled file')
}
})()`
component.code += IIFEcss
// remove from final bundle
delete bundle[css_filename]
},
},
],
},
},
})
I created a boilerplate Vite project for this problem:
https://github.com/mvsde/svelte-micro-frontend
Maybe the configuration helps with your case:
import { defineConfig } from 'vite'
import { svelte } from '#sveltejs/vite-plugin-svelte'
export default defineConfig({
plugins: [
svelte({
emitCss: false
})
],
build: {
assetsDir: '',
sourcemap: true,
lib: {
entry: 'src/main.js',
formats: ['iife'],
name: 'SvelteMicroFrontend',
fileName: 'svelte-micro-frontend'
}
}
})
I had the same issue and was able to fix by editing vite.config.ts as follows tested on vite#2.3.8
export default {
build: {
rollupOptions: {
output: {
manualChunks: undefined,
},
},
},
};
If you are working with Svelte, you can use emitCss:
export default defineConfig({
plugins: [svelte({
emitCss: false,
})],
})
As manualChunks are no longer working in a latest versions of Vite, there's no any way to combine all the chunks into one.
But found a hacky solution to have an index.html + bundle.js after the build: https://github.com/d-velopment/SvelteKit-One-Bundle - it rewraps the project's initial .js files to go from bundle.js, which could be loaded from index.html or external project.
I am working on a project with Svelte and the material design library Svelte Material UI.
This material design library requires SASS, so I installed a preprocessor with npm install svelte-preprocess and added preprocess: autoPreprocess() in rollup.config.js. So I now have:
plugins: [
svelte({
// enable run-time checks when not in production
dev: !production,
// we'll extract any component CSS out into
// a separate file - better for performance
css: css => {
css.write('public/build/bundle.css');
},
preprocess: autoPreprocess()
}),
routify({ singleBuild : true}),
replace({
// stringify the object
APPENV: JSON.stringify({
isProd: production,
...config().parsed // attached the .env config
}),
}),
// more stuff
]
I have a file smui.js with this content:
import Button from '#smui/button';
import Checkbox from '#smui/checkbox';
import Chips from '#smui/chips';
import Dialog from '#smui/dialog';
import FormField from '#smui/form-field';
import Select from '#smui/select';
export {
Button,
Checkbox,
Chips,
Dialog,
FormField,
Select
}
In my index.svelte file I am importing the above this way: import * as Smui from "../smui.js";.
Instead of a success message with the port on which the app should run, I get:
[!] Error: Unexpected character '#' (Note that you need plugins to import files that are not JavaScript)
node_modules\#smui\dialog\_index.scss (1:0)
1: #import "smui-theme";
^
2: #import "./style";
Error: Unexpected character '#' (Note that you need plugins to import files that are not JavaScript)
What am I doing wrong?
I had the same issue and somehow I managed to fix this with rollup-plugin-postcss plugin. Update your rollup.config.js with the following code and you should have _smui-theme.scss in your one of sass directories.
import postcss from 'rollup-plugin-postcss'
...
plugins: [
svelte({
// enable run-time checks when not in production
dev: !production,
// we'll extract any component CSS out into
// a separate file - better for performance
css: css => {
css.write('public/build/bundle.css')
}
}),
postcss({
extensions: ['.css'],
extract: true,
minimize: true,
use: [['sass', { includePaths: ['./src/(yoursass-directory-name)', './node_modules'] }]]
})
I've never used #import to import components from a NPM package, but at the readme package you're referencing it recommends using 'import x from" svelte-material'. Also pay attention that svelte-preprocess won't be supported by the package you're referencing, take a look at the readme:
To bundle this in your own code, use a Sass processor (not a Sass Svelte preprocessor, but a Sass processor).
I'm working on an Open Source D3/React component library and I'm trying to bundle the library using Rollup.js to offer code splitting, three shaking, etc.
The library is already published in GitHub and NPM and you can check a codesandbox using the library for a reference in case you want to try it.
Next I'm gonna try to highlight the different issues I'm experiencing with this bundle.
The library has already been tested using the code directly in a project and it works perfectly, so the problem is with the bundle and I assume that I'm doing something wrong with the Rollup.js configuration file in my project.
import { readdirSync } from 'fs';
import path from 'path';
import babel from 'rollup-plugin-babel';
import commonjs from 'rollup-plugin-commonjs';
import external from 'rollup-plugin-peer-deps-external';
import replace from 'rollup-plugin-replace';
import resolve from 'rollup-plugin-node-resolve';
import { terser } from 'rollup-plugin-terser';
const CODES = [
'THIS_IS_UNDEFINED',
'MISSING_GLOBAL_NAME',
'CIRCULAR_DEPENDENCY',
];
const getChunks = URI =>
readdirSync(path.resolve(URI))
.filter(x => x.includes('.js'))
.reduce((a, c) => ({ ...a, [c.replace('.js', '')]: `src/${c}` }), {});
const discardWarning = warning => {
if (CODES.includes(warning.code)) {
return;
}
console.error(warning);
};
const env = process.env.NODE_ENV;
const plugins = [
external(),
babel({
exclude: 'node_modules/**',
}),
resolve(),
replace({ 'process.env.NODE_ENV': JSON.stringify(env) }),
commonjs(),
env === 'production' && terser(),
];
export default [
{
onwarn: discardWarning,
input: 'src/index.js',
output: {
esModule: false,
file: 'umd/silky-charts.js',
format: 'umd',
name: 'silkyCharts',
},
plugins,
},
{
onwarn: discardWarning,
input: getChunks('src'),
output: [
{ dir: 'esm', format: 'esm', sourcemap: true },
{ dir: 'cjs', format: 'cjs', sourcemap: true },
],
plugins,
},
];
The Errors
When I try to use the library using the production bundle (which is the default) directly from the NPM package I got the following error coming from one of the chunks node_modules/silky-charts/esm/chunk-501b9e58.js:5833
TypeError: react__WEBPACK_IMPORTED_MODULE_0___default(...) is not a function
If I stead use the development bundle I get a different error:
Failed to compile
../silky-charts/esm/index.js
Module not found: Can't resolve 'react' in '/Users/davidg/Development/personal/silky-charts/esm'
This error force me to install React, ReactDOM, and styled-components as devDependencies in the project for the library have access to these projects code.
After installing the devDependencies the error I get is the next one:
Hooks can only be called inside the body of a function component.
I already filled an issue in the React project page and according to them this is not a React issue but maybe a Webpack's since is usual to find this error when you have to install React in both the project and the library and Webpack finds there is two instances of React, and I kind of agree since the error varies depending on bundle type or the way the importer project is run as you can see in the codesandbox.
I hope you can help me to spot the error in the Rollup configuration file and if you feel like doing a PR in the project event better 😀.