First of all I would like to thank for the excellent tool!
Before version 0.5.0, building with cjs and es format produced unbundled modules with required/imported dependencies (i.e. output of entry modules didn鈥檛 contain code of its dependencies).
Is it possible to get the same result in the current version (0.11.0)?
You dependencies should not get bundled
Which command are you running to build(/bundle) your library?
@gamtiq 0.4.4? That's pretty old at first and it probably was wrong behvaior.
Anyway, you should be able to use --external (comma-separated list) for this, or just add them in dependencies or peerDependencies. It's general practice when you want to bundle them to put them in devDepdendecies, since most similar tools automatically get deps and peerDeps and put them as "external" (so they won't get bundled).
Yup! devDependencies get bundled, dependencies & peerDependencies don't.
devDependencies get bundled
It's not exactly correct to say that. You get bundled the dependencies that your code uses - unless they are in deps & peerDeps, it's not bundling all devDeps. You can put your dependencies wherever you want - e.g. optionalDependencies.
Anyway, just a bit clarification for total newcommers.
The talk is about local dependencies (not from npm).
The following example should clarify the case.
package.json
{
"name": "some-lib",
"version": "1.0.0",
"main": "src/index.js",
"scripts": {
"build-commonjs": "microbundle build \"src/*.js\" --output dist/commonjs --format cjs --strict --no-compress",
"build-esm": "microbundle build \"src/*.js\" --output dist/es-module --format es --no-compress"
},
"devDependencies": {
"microbundle": "0.11.0"
}
}
src/a.js
export function a() {
}
src/index.js
import { a } from './a';
export function b() {
return a();
}
After running npm run build-commonjs you have got the following output.
dist/commonjs/a.js
'use strict';
function a() {}
exports.a = a;
//# sourceMappingURL=a.js.map
dist/commonjs/some-lib.js
'use strict';
var a_js = require('./a.js');
function b() {
return a_js.a();
}
exports.b = b;
//# sourceMappingURL=some-lib.js.map
You can see that local dependency is not bundled but imported.
The same is true for npm run build-esm.
After running npm run build-commonjs you have got the following output.
dist/commonjs/a.js
'use strict';
function a() {}
exports.a = a;
//# sourceMappingURL=a.js.map
dist/commonjs/some-lib.js
'use strict';
function a() {}
function b() {
return a();
}
exports.b = b;
//# sourceMappingURL=some-lib.js.map
You can see that dependency from a.js is bundled into some-lib.js.
The same is true for npm run build-esm.
Versions 0.5.0+ have similar output.
Is it possible to get for current version of microbundle the same result as for version 0.4.4?
Don't think so.
That totally not making sense to me, sorry. Seems like bug in that 0.4.4 version I guess.
What you want is not bundling but building, so you can just use Babel for this which outputs the same file structure but transpiled.
Why would you want such output? Why would you use microbundle or anything built on top of Rollup or Webpack when you don't want everything to be bundled in one file?
Recent versions of Rollup support that though (or similar thing, didn't tried it yet) with preserveModules, but I don't see the point at all.
One reason for preserveModukes is to still benefit from tree shaking and rollup plugin processing. The use case is niche but it is there.
Other thing than preserveModules is ability to output multiple entry files - and the use case for this is to bundle everything as flat as possible, but create multiple public entry points with code shared between them by automatically created chunks. It exposes what we want to be public, but hides everything that is supposed to be private
Why would you want such output? Why would you use microbundle or anything built on top of Rollup or Webpack when you don't want everything to be bundled in one file?
The short answer is simplicity.
microbundle allows to bypass complex configuration of build tools (e.g. Babel, Rollup, webpack etc).
For me the behavior of version 0.4.4 makes sense. Using one tool (microbundle) I can get transpiled but not bundled CommonJS and ESM builds and bundled UMD build.
if you don't want bundling you might just want to use babel with babel-preset-env
@ForsakenHarmony this would force @gamtiq to create multiple babel tasks (1 for ESM, 1 for CJS) and he'd still probably have to use rollup/microbundle to output UMD. Gains from using microbundle in this case are questionable - but it's nice to have a single tool that can do its job with 0 config.
But even besides that, there are reasons for bundling into multiple entry points. https://preconstruct.tools/guides/when-should-i-use-multiple-entrypoints
For example in emotion we have 2 entry points for one of packages - @emotion/styled and @emotion/styled/base. This is because that main entry looks like this:
https://unpkg.com/browse/@emotion/styled@11.0.0-next.3/dist/styled.browser.esm.js
It just adds some convenience stuff onto /base entry - but with a babel plugin we actually rewrite imports and call sites to use that /base directly.
In this particular example benefits of using rollup are not as apparent, but in the case of redux-saga becomes more clear:
https://unpkg.com/browse/@redux-saga/core@1.1.3/dist/
There are 2 entry points - redux-saga and redux-saga/effects - and they share common (private) code which gets put into auto-generated chunks (those io-*.js in here).
If it's just about having multiple entrypoints, you can currently do that
We have it setup for microbundle itself
https://github.com/developit/microbundle/blob/master/package.json#L11
(but I guess that's cjs only, I'm not entirely sure how well it works with multiple formats)
The thing is that all this is already totally different behavior and new feature to comment (not bundling at all even local deps).
I'm guessing that @gamtiq can currently do --external ./a.js and for all other local files. It's a bit to much but... that's for now.
Reading the through comments here, it sounds very much like microbundle doesn't fit into the problem space the original poster is looking for. microbundle originated from the preact repo where we were looking for ways to make our customized build pipeline reusable. As the name microbundle implies we do bundle the code for performance reasons for preact.
Supporting non-bundled code is a non-trivial task. My understanding is that there may have been some accidental behavior like that possible in a very early version. As far as I'm aware it was not a planned feature, hence the reliance on a bundler like rollup at the core.
Nonetheless it's an interesting use case. I'm sure the team is happy to review any PRs or give guidance of the code in this repo if needed. I don't think it makes much sense for the microbundle team to work on that, because it's just a thin wrapper around rollup with some pre-configured plugins. If rollup or some plugin allows for such a feature to be easily implemented, it would be worth to check that out.
Addition to the example with microbundle 0.4.4.
After running
npx microbundle build --output dist/cjs-bundle --format cjs --strict --no-compress
you have got just one bundled file dist/cjs-bundle/some-lib.js:
'use strict';
function a() {}
function b() {
return a();
}
exports.b = b;
//# sourceMappingURL=some-lib.js.map
After running
npx microbundle build --output dist/es-bundle --format es --no-compress
you have got just one bundled file dist/es-bundle/some-lib.js:
function a() {}
function b() {
return a();
}
export { b };
//# sourceMappingURL=some-lib.m.js.map
So version 0.4.4 (and some versions before, at least 0.3.1 too) allows to get bundled and unbundled CJS/ES builds of a library.
It seems that versions 0.5.0+ have an unintentional regress regarding the case.
@marvinhagemeister, exactly.
Sorry @gamtiq, man, are you ignoring at all what we are all talking about?
It seems that versions 0.5.0+ have an unintentional regress regarding the case.
It's exactly the opposite thing. It was unintentional behavior in very early versions.
allows to get bundled and unbundled CJS/ES builds of a library.
How? I don't see how your last comment is different than the linked one, and in general how these examples proves all this. If microbundle build was getting unbundled output, how was getting bundled one?
Don't get me wrong, I just don't get it.
are you ignoring at all what we are all talking about?
No. Sorry if my previous comment caused such impression.
Using microbundle 0.4.4 it is possible to get bundled and unbundled versions of a library.
After running
npx microbundle build "src/*.js" --output dist/commonjs --format cjs --strict --no-compress
you have got unbundled CJS build that is described in my example.
After running
npx microbundle build --output dist/cjs-bundle --format cjs --strict --no-compress
you have got bundled CJS build as described in my previous comment.
Ooh, i just spot the difference between the commands - in first there is input passed (glob pattern), and in the second there isn't input. ~Can you (i can check later) in the source code of it how the no input case was handled.~
I'm guessing the result of the first command (with glob pattern, more specifically a globstar) was exactly because the glob pattern. What's the result now since it is still supporting multiple entrypoints like microbundle itself is doing ({index,cli}.js)
@gamtiq interesting enough, it works for me as you expect in both 0.4.4 and the latest.
With all possible variants:
# not bundled (0.4.4 and latest)
microbundle build 'src/*.js' --format cjs,es --no-compress
# not bundled (0.4.4 and latest)
microbundle build 'src/{index,add}.js' --format cjs,es --no-compress
# bundled (0.4.4 and latest)
microbundle build --format cjs,es --no-compress
https://github.com/tunnckoCore/mb-issue-514
Still possible. And yet, i still think it's incorrect behavior.
I've checked https://github.com/tunnckoCore/mb-issue-514 and cannot get not bundled build for latest microbundle (0.11.0).
After running
npx microbundle build "src/*.js" --format cjs,es --no-compress --output dist/build-1
or
npx microbundle build "src/{index,add}.js" --format cjs,es --no-compress --output dist/build-2
I have got the following output for index.js
function add(a, b) {
return a + b;
}
function bar() {
return add(1, 2);
}
exports.bar = bar;
//# sourceMappingURL=mb-issue-514.js.map
Perhaps the issue depends on environment.
My environment is the following: Windows 7, node 10.15.3, npm 6.4.1.
Oh, of course. Are you using the Windows prompt or using something like git bash or github desktop or..? I don't know. I don't think Windows support globs and that's the problem. Unbundled to work, the input need to be some glob pattern (*.js or {}) instead of actual file.
Now I see and understand why issue templates are good idea :D
I can confirm that the issue is specific to Windows.
I can get not bundled build by microbundle 0.11.0 on macOS with node 10.15.3 and npm 6.4.1.
Does it matter if you put the build step in an npm script instead of running it directly?
And with or without quotes, see https://github.com/developit/microbundle/blob/master/package.json#L11
It doesn't matter whether a build is started by npx or by a npm script. The result is the same: bundled code.
I've tried the following variants of npm scripts:
microbundle build --format cjs --no-compress --output dist/build-1 src/*.jsmicrobundle build --target=node --format cjs --no-compress --output dist/build-1 src/*.jsmicrobundle build --format cjs --no-compress --output dist/build-2 src/{index,add}.jsmicrobundle build --target=node --format cjs --no-compress --output dist/build-2 src/{index,add}.jsFlags doesn't matter. The problem is in globbing.
Try 'src/*.js' and 'src/{index,add}.js'. This way the glob will be passed directly to the microbundle not expanded by the terminal.
Usage of single quotes in npm script
"scripts": {
"build-1": "microbundle build --format cjs --no-compress --output dist/build-1 'src/*.js'"
}
results in the following error:
> microbundle build --format cjs --no-compress --output dist/build-1 'src/*.js'
WARN missing package.json "name" field. Assuming "mb-issue-514".
Error: ENOENT: no such file or directory, scandir ''src'
at Object.readdirSync (fs.js:785:3)
at walk (mb-issue-514\node_modules\tiny-glob\sync.js:12:20)
at module.exports (mb-issue-514\node_modules\tiny-glob\sync.js:78:3)
at mb-issue-514\node_modules\microbundle\dist\microbundle.js:327:97
at Array.map (<anonymous>)
at _temp4 (mb-issue-514\node_modules\microbundle\dist\microbundle.js:327:68)
at _temp5 (mb-issue-514\node_modules\microbundle\dist\microbundle.js:332:46)
at _temp6 (mb-issue-514\node_modules\microbundle\dist\microbundle.js:335:44)
at getInput (mb-issue-514\node_modules\microbundle\dist\microbundle.js:344:47)
at mb-issue-514\node_modules\microbundle\dist\microbundle.js:433:30
Similar error is for './src/*.js':
Error: ENOENT: no such file or directory, scandir ''.\src'
Interesting. Hm so, microbundle is doing something interesting. I'll check later.
Unless someone comments, I'm going to assume this is fixed in 0.12 / 0.13. Please re-open if not.
Unfortunately the issue takes place in version 0.13.
See gamtiq/microbundle-issue-514 to reproduce.
Most helpful comment
Usage of single quotes in npm script
results in the following error:
Similar error is for
'./src/*.js':Error: ENOENT: no such file or directory, scandir ''.\src'