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).
Related
I am trying to remove unused CSS from my code, but I am struggling with tree-shaking my CSS files.
I decided to use rollup instead of webpack, because it was said that tree-shaking is a core idea behind the library, but now it seems to me that rollup is not capable of tree-shaking CSS files at all.
What I am doing is the following:
I create a rollup config for my page:
export default [
{
input: "path/to/index.js",
output: [
{
format: "esm",
file: "path/to/output/index.min.js",
},
],
treeshake: true,
plugins: [
postcss({
extract: true,
plugins: [cssnano()],
extensions: [".css"],
}),
resolve(),
commonjs(),
terser(),
],
},
Then I have my index.js file where I import my CSS and my JS:
import "../path/bootstrap.css";
import "../path/css/nav.css";
import "../path/css/footer.css";
import "bootstrap/js/dist/carousel";
import "../modules/css/example.css/";
import { example_function } from "../path/to/js/example.js";
example_function();
I run the rollup bundler and it creates a minified JS and a minified CSS file. So far so good, but it still includes the complete bootstrap classes for the CSS. I would like to tree-shake the CSS and only include the classes that are actually used.
Are there some settings that I am missing? Or is this not as easyly possible as I hope to achieve it.
I am trying to bundle my stylesheets which should use bootstrap v5. I can bundle my CSS files without a problem but I cannot get bootstrap to work. The bundler runs through, but bootstrap styles are not included.
What I did:
I installed bootstrap with npm install bootstrap (https://getbootstrap.com/docs/5.0/getting-started/download/#npm)
I included bootstrap into:
either my JS file with import 'bootstrap';
in my CSS with #import "node_modules/bootstrap/dist/css/bootstrap"; (This is not working because it tells me that my file is not found)
My rollup.config:
import resolve from "#rollup/plugin-node-resolve";
import commonjs from "rollup-plugin-commonjs";
import { terser } from "rollup-plugin-terser";
import postcss from "rollup-plugin-postcss";
import cssnano from "cssnano";
export default [
{
input: "project/static/src/inputs/index.js",
output: [
{
format: "esm",
file: ""project/static/src/outputs/index.min.js",",
},
],
plugins: [
postcss({
extract: true,
plugins: [cssnano()],
extensions: [".css"],
}),
resolve({
jsnext: true,
browser: true,
}),
commonjs(),
terser(),
],
},
];
This config creates a separate CSS file because I set extract = true for the postcss plugin.
Then, in my CSS file:
#import "../modules/css/example.css";
#import "node_modules/bootstrap/dist/css/bootstrap";
.container-example {
margin-top: -1.5rem;
}
In my JS
import "./example.css";
import 'bootstrap';
//more JS here
I then run the bundler and it bundles my JS and also my styles. But it does not include any bootstrap styles... I can't seem to figure out why. Maybe because BS is all about SASS? Any ideas? Help is very much appreciated.
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 😀.
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,
I'm currently creating a bower package that exports a single ES6 module.
When building the dist for my package, I'm using rollup to move all my internal modules into a single module, exporting only the one module.
Gulp task:
// Bundle ES6 modules into a single file
gulp.task('bundle', function(){
return gulp.src('./src/GuacaMarkdownEditor.js', {read: false})
.pipe(rollup({
// any option supported by rollup can be set here, including sourceMap
// https://github.com/rollup/rollup/wiki/JavaScript-API
format: 'es6',
sourceMap: true
}))
.pipe(sourcemaps.write(".")) // this only works if the sourceMap option is true
.pipe(gulp.dest('./dist'));
});
This all works fine, but I'm importing some dependencies from other bower packages which I don't want to bundle with my module (jQuery, font-awesome).
My problem is this: How can I keep bundling MY code and keep the ES6 import statements for bower packages - but without rollup bundling the external code into my bundle?
Example:
"use strict";
import $ from 'jquery'; // dont bundle this!
import GuacaAirPopUp from './GuacaAirPopUp'; // bundle this!
export
default class GuacaMarkdownEditor {
...
}
You can use this rollup plugin rollup-plugin-includepaths.
It allows you to import modules by name and define modules should be excluded from the bundle. I used it in a rollup.config.js:
import babel from 'rollup-plugin-babel';
import includePaths from 'rollup-plugin-includepaths';
var includePathOptions = {
paths: ['es6'],
include: {
'd3': './global/js/' + 'base/d3.min' // include library in es6 modules
},
external: ['d3'] // but don't bundle them into bundle.js
};
export default {
entry: './es6/entry.js',
plugins: [
includePaths(includePathOptions),
babel()
],
format: 'amd',
dest: 'build/bundle.js',
sourceMap: true
};
And in the es6 modules:
// not using relative path since it is handled by the plugin
import d3 from 'd3';
import other from 'otherModules';
//...
More discussion about external resolution here
It seems that rollup will detect named imports (as opposed to relative paths), as external dependencies.
When bundling this module:
import GuacaAirPopUp from './GuacaAirPopUp';
import ControlHandlerService from './ControlHandlerService';
import DefaultHandlerConfig from './DefaultHandlerConfig';
import toMarkdown from 'to-markdown';
import $ from 'jquery';
The bundler gave these messages:
Treating 'to-markdown' as external dependency
Treating 'jquery' as external dependency
When bundling the application that used this module, jquery was imported correctly using browserify.
Answered already by anthr however if you want to exclude your own made modules down below I believe is a clear explanation.
https://github.com/rollup/rollup/wiki/JavaScript-API#external
A list of IDs of modules that should remain external to the bundle
// main.js
import myMod from './my-module'; // <-- this module you don't wanna import
// build.js <--- gulp file
import * as path from 'path';
//...more of you gulp file code
rollup.rollup({
entry: 'app.js',
external: [
'./my-module', // <--- node module to be excluded from the bundle
path.resolve( './src/special-file.js' ) // <--- file you made to be excluded from the bundle
]
}).then(...)
//...more of you gulp file code
// Bundle ES6 modules into a single file
gulp.task('bundle', function(){
return gulp.src('./src/GuacaMarkdownEditor.js', {read: false})
.pipe(rollup({
// any option supported by rollup can be set here, including sourceMap
// https://github.com/rollup/rollup/wiki/JavaScript-API
format: 'es6',
sourceMap: true
}))
.pipe(sourcemaps.write(".")) // this only works if the sourceMap option is true
.pipe(gulp.dest('./dist'));
});