DEV Community

Pacharapol Withayasakpunt
Pacharapol Withayasakpunt

Posted on

What's your way of publishing Node.js library for the browser? (also, introducing Rollup)

  • Do you attach to window object, or is there a better alternative?
    • How many namespaces do you usually attach?
    • How do you maintain both browser version and bundler version?
  • Do you require your library users to use a bundler or Node.js, for simplicity's sake?
  • If you bundle for library users, which bundler do you use?
  • How many percentage of browsers do you support? Which ES version?

BTW, I have just started using Rollup to bundle TypeScript for <script type="module">, so that I don't have to attach to window object.

  • Webpack just couldn't target ESM
  • Bundled ESM might also be usable in Deno.
  • Output of non-minified Rollup is readable. Webpack is not, and is full of eval. (Even minified version of Rollup is relative readable as well.)
  • tsconfig.json uses "module": "commonjs" (so that I can run ts-node, ts-mocha and publish for Node, without esm), but rollup.config.js uses esnext.
    • I also use tsc to build for Node. Rollup just cannot properly do it. And Rollup cannot generate declaration and declarationMap
// rollup.config.js

import typescript from '@rollup/plugin-typescript'
import minify from 'rollup-plugin-babel-minify'

const getConfig = ({ output, isMinify }) => {
  return {
    input: 'src/index.ts',
    output: {
      file: output,
      format: 'esm',
      sourcemap: true
    },
    plugins: [
      typescript({
        module: 'esnext'
      }),
      ...(isMinify ? [
        minify({
          comments: false
        })
      ] : [])
    ]
  }
}

export default [
  getConfig({ output: 'lib/index.mjs' }),
  getConfig({ output: 'lib/index.min.mjs', isMinify: true })
]
Enter fullscreen mode Exit fullscreen mode
  • If you wonder about package.json, it is
{
  "main": "lib/index.js",
  "module": "lib/index.mjs",
  "unpkg": "lib/index.min.mjs",
  "types": "lib/index.d.ts",
  "files": [
    "lib",
    "src"
  ],
  "scripts": {
    "build": "rimraf lib && rollup -c && yarn tsc",
    "tsc": "tsc -P src/tsconfig.json",
    "prepack": "yarn build && yarn deploy"
  }
}
Enter fullscreen mode Exit fullscreen mode
  • And tsconfig.json
{
  "compilerOptions": {
    "target": "ES2017",
    "module": "commonjs",
    "declaration": true,
    "declarationMap": true,
  }
}
Enter fullscreen mode Exit fullscreen mode

GitHub logo patarapolw / any-serialize

Serialize any JavaScript objects, as long as you provides how-to. I have already provided Date, RegExp and Function.

Features are

  • Serialize anything.
  • Deserialize almost anything, but if you tweak a little, you can make it work with anything as well.
  • Hash anything to string.
  • Clone anything.
  • No external dependencies, and highly customizable.

Top comments (2)

Collapse
 
saurabhdaware profile image
Saurabh Daware 🌻

I'm doing super hacky stuff. I usually write my own build scripts that reads code from different files and writes them into the new files, then I remove the export import keywords from the code string and minify it.

Here's my build script

const fse = require('fs-extra');
const minify = require('@node-minify/core');
const terser = require('@node-minify/terser');


console.log("Build started... \n🌻");

fse.removeSync('dist');
fse.copySync('src', 'dist');

// Read from both the files
const voicesFile = fse.readFileSync('src/voices.mjs');
const indexFile = fse.readFileSync('src/index.mjs');

// Bundle them together
let bolFile = voicesFile + '\n' + indexFile;

// Remove export import keywords
bolFile = bolFile
  .replace(/\b.*(export default).*/g, '')
  .replace(/\b(export)\b/g, '')
  .replace(/\b.*(import).*/g, '')

// Write into new files
fse.writeFileSync('dist/bol.js', bolFile);

// Create a minified version of new file
minify({
  compressor: terser,
  input: 'dist/bol.js',
  output: 'dist/bol.min.js',
  callback: function(err, min) {}
});

console.log(" DONE 🎉");

Though this is not ideal when you have to change the directory structure multiple times. This just works for me since I don't have to add/remove new files for that particular usecase

Collapse
 
amiceli profile image
amiceli

For little project I use parcel without any conf. It's very easy to build or server and rollup for other projects.