Isomorphic + Rollup + Package.json
It took me a while to piece this all together, so I'm mainly posting these notes here for myself as I go along.
We want same code for nodejs and the browser, so in package.json we set:
// package.json
...
"main": "dist/index.js",
"browser": "lib/index.browser.js"
...
But maybe we want both ES and UMD modules available to the browser user, so we break browser out:
// package.json - browser expanded
"main": "dist/index.js",
"module": "dist/index.esm.js",
"browser":{
"dist/index.js": "dist/index.browser.js",
"dist/index.esm.js": "dist/index.browser.esm.js"
},
Now, depending on how the user imports the package, will determine what file they get. If they use index.js
from nodejs the user will get dist/index.js
but if they use index.js
from the browser they will get dist/index.browser.js
!
Make the files
We can use Rollupjs to make these files
// rollup.config.js
...
import pkg from './package.json'
...
export default [
// browser-friendly builds
{
input: 'src/main.js',
output: [{
name: 'myPkgName',
file: pkg.browser['dist/index.js'], // from package.json
format: 'umd'
},
{
file: pkg.browser['dist/index.esm.js'], // from package.json
format: 'es'
}]
plugins: [
resolve(), // so Rollup can bundle modules
babel({
exclude: ['node_modules/**']
}),
commonjs(), // so Rollup can convert to ES module
]
},
// CommonJS (for Node) and ES module (for bundlers) build.
// (We could have three entries in the configuration array
// instead of two, but it's quicker to generate multiple
// builds from a single configuration where possible, using
// an array for the `output` option, where we can specify
// `file` and `format` for each target)
{
input: 'src/main.js',
output: [
{ file: pkg.main, format: 'cjs' }, // from package.json
{ file: pkg.module, format: 'es' } // from package.json
],
plugins: [
babel({
exclude: ['node_modules/**']
})
]
}
];
Use the ES Module
Now that you have an ES module, you can import it into your code
import NamedExport from 'myCoolModule'
Bundle your code (again) with Rollup in the same way, perhaps using a front end framework like Svelte.
// bundled output from a framework, like Svelte
build/bundle.js
Now that you have all these modules, and they are bundled into the code, they can also be used for cool things like code-splitting and dynamic imports.
// index.html
<!-- This standard way only works if the browser
is modern and supports dynamic imports -->
<script defer type="module" src='/build/main.js'></script>
Dynamic Import an ES module in any browser
Use dimport:
<!-- https://www.npmjs.com/package/dimport -->
<script defer type="module" src="https://unpkg.com/dimport?module"
data-main="/build/main.js"></script>
<script defer type="nomodule" src="https://unpkg.com/dimport/nomodule"
data-main="/build/main.js"></script>
Refs:
dimport
Dynamic Imports
Svelte Code Splitting
Svelte Code Splitting without Sapper
Code Splitting Routify
Target based Dependency Transpiling
Package.json Browsr Swithcing
Pkg.json Browser Tests
Rollup Config: Multi-inputs
Rollup Config: babel
Top comments (0)