@s-ui/bundler

9.57.0 • Public • Published

sui-bundler

Config-free bundler for ES6 React apps.

Features:

  • Simple CLI for prod and dev environment
  • Unique solution for bundling; no boilerplate, no config.
  • Remote improvements inherited transparently (ej: monitoring, PWA, etc)

Installation

$ npm install @s-ui/bundler --save-dev

Usage for web app bundling

Add bundling scripts to your package.json

{
  "name": "my-awesome-package",
  "version": "1.0.0",
  "scripts": {
    "build": "sui-bundler build -C",
    "start": "sui-bundler dev"
  }
}

Requirements for web app bundling

node 12 version is required.

Folder structure

Refer to example folder to see what's expected, which is basically:

├── package.json
└── src
    ├── index.html
    └── app.js

With index.html as app home andapp.js as entry point.

CLI

Development

$ sui-bundler dev

While developing your app, you will have HMR (Hot Module Reloading). Default port for your website is 3000, but it will assign automatically a free port for you if this one is busy.

How to link packages

sui-bundler give us the oportunity to link npm packages with --link-package. This argument accepts relative and absolute paths. sui-bundler internally will change the path of the files to use. So it goes directly to our local files. The reason we use link-package instead of npm link is because it gives a plus of performance when we are linking packages. The link is cancelled as soon as we stop/cancel the terminal process.

Requirements

  • Only available in DEV mode.
  • A src/index.js have to exist in the path provided

Example:

$ sui-bundler dev --link-package=/absolute_path/to/npm_package
$ sui-bundler dev --link-package=../relative_path/to/npm_package

To link more than one package at time, use as many times as desired the argument.

$ sui-bundler dev --link-package=/absolute_path/to/npm_package --link-package=/absolute_path2/to/npm_package

You can also use -l as a shorthand to link a package.

$ sui-bundler dev -l /absolute_path/to/npm_package -l /absolute_path2/to/npm_package

If you want to link all the packages inside a monorepo-multipackage. Use the flag --link-all pointing to the folder where each package lives. For example, if you want to link all the components in a Studio, the command should be:

$ sui-bundler dev --link-all ../frontend-ma--uilib-components/components

You can use -L as a shorthand to link all packages.

$ sui-bundler dev -L ../frontend-ma--uilib-components/components

And of course you can combine link-all and link-package flags

Production

$ sui-bundler build

It will build a deployable folder public where you can find all your statics. If you wish to remove the content of the folder before generating new files, just use the flag --clean | -C If you want you can use the flag --link-package with this commands

Library

You can use sui-bundler to bundle a package as a library that can be injected with a simple script tag.

$ sui-bundler lib

You should create an entry file that assigns your lib to your desired namespace:

// umd.js
import MyFancyModule from '/src/index.js'
window.namespace.fancy = MyFancyModule

You should create an entry file that assigns your lib to your desired namespace:

And then execute sui-bundler lib with your destination config:

sui-bundler lib umd/index.js -o lib/fancy -p http://my-cdn.com/fancy

sui-bundler lib will add your package version as subfolder:

  • -o lib/fancy outputs to ./lib/fancy/0.0.0/
  • -p http://my-cdn.com/fancy sets http://my-cdn.com/fancy/0.0.0 as public path for chunks loading.
  • -r http://my-cdn.com/fancy sets http://my-cdn.com/fancy as public path for chunks loading, discarded the version subdirectory.

Automatic UMD

You can use --umd option to publish directly from your original entry file:

$ sui-bundler lib src/index.js -o umd/fancy -p http://my-cdn.com/fancy --umd="MyFancyLibraryNamespace"

Then you can find your library directly in the provided namespace variable: window.MyFancyLibraryNamespace or window.MyFancyLibraryNamespace.default for ES6 exports.

Configuration

This tool works with zero configuration out the box but you could use some configuration in order to optimize or adapt the output to your needs. For that, you need to add a property sui-bundler inside a config property in the package.json of your project.

extractComments: Determine whether comments shall be extracted to a separate file or not. Like LICENSE comments. (default: false)

targets: Object with information about the browser and version supported. (default: see the next example)

{
  "config": {
    "sui-bundler": {
      "supportLegacyBrowsers": true, // default
      "onlyHash": "true",
      "env": ["APP_NAME", ["USER", "DEFAULT_VALUE"]],
      "vendor": ["react", "react-dom"],
      "cdn": "https://url_to_me_cdn.com/",
      "externals-manifest": "https://url_to_me_cdn/manifest.json",
      "alias": {
        "react": "preact"
      },
      "offline": true,
      "sourcemaps": {
        "dev": "cheap-module-eval-source-map",
        "prod": "hidden-source-map"
      }
    }
  }
}

The URL to the CDN MUST end with a slash /

## OnlyHash

In windows system filenames with ~ could produce errors. To avoid that you can use the flag onlyHash in your configuration to go form names like Home.123.js to 123.js. And that should solve the issue.

Offline and SW support

Offline feature is deactivated by default. If you want to activate, you need to create the static src/offline.html file. No resource loaded by this page will be cached so watch out adding images or external scripts as they won't work in offline mode. You also need to configure a serviceWorker in the entry point of your app:

If you have the page "src/offline.html" in your project, but you have configured the option "fallback" in your package.json. The generated SW will manage the fallback and ignore your offline page.

import {register, unregister} from '@s-ui/bundler/registerServiceWorker'
register({
  first: () => window.alert('Content is cached for offline use.'),
  renovate: () => window.alert('New content is available; please refresh.')
})

You should pass a handler in order to handle when content gets cached for the first time the content and another when you get new content and want to handle how to show a notification to the user in order to let him decide if he wants to refresh the page.

If you want to remove your ServiceWorker, you need to use the method unregister, the same way you used the register method before.

Only Caching

It's possible to create a service worker that caches all static resources

There are two ways to activate the statics cache option:

  1. Create a src/offline.html page as mentioned in the offline section
  2. Add the staticsCacheOnly option within the package.json like this:
{
  "sui-bundler": {
    "offline": {
      "staticsCacheOnly": true
    }
  }
}

Statics will be cached but no offline page will be activated

Externals Manifest

If your are using an external CDN to store statics assets that are now managed by Webpack, like SVG or IMGs, you can create a manifest.json file in the root of your CDN (likehttps://spa-mock-statics.surge.sh/manifest.json`).

If you define the externals-manifest key in the config pointing to this link, sui-bundler will replace any ocurrence of each key for the value

If in your CSS you have:

#app {
  color: blue;
  background: url('https://spa-mock-statics.surge.sh/images/common/sprite-sheet/sprite-ma.png')
    no-repeat scroll;
}

After compile you will get:

#app {
  color: #00f;
  background: url(https://spa-mock-statics.surge.sh/images/common/sprite-sheet/sprite-ma.72d1edb214.png)
    no-repeat scroll;
}

Or if in your JS you have:

<img
  src={'https://spa-mock-statics.surge.sh/images/common/mis-anuncios2.gif'}
/>

After compile will be:

<img src="https://spa-mock-statics.surge.sh/images/common/mis-anuncios2.5daef216ab.gif">

The main idea is have a long term caching strategy for the hashed files. But you NEVER must cache the manifest.json file.

Create the manifest file is up to you, but your file must follow this schema.

{
  /images/favicon.ico: "/images/favicon.23f4ccc7ca.ico",
  /images/common/arrow-down.png: "/images/common/arrow-down.2d12edfb00.png",
  /images/common/icons-spritesheet.png: "/images/common/icons-spritesheet.9498fa3745.png",
}

If you setup the NODE_ENV=development then this loaders will be disabled.

Configuring source map generation

SUI-bundler generates no sourcemaps by default but you can change this behaviour and configure them in the sui-bundler section of your package.json. Different values can be configured for development (dev) and production (prod) webpack configs.

{
  "sui-bundler": {
    "sourcemaps": {
      "dev": "cheap-module-eval-source-map",
      "prod": "hidden-source-map"
    }
  }
}

Check all possible values accepted by webpack in the devtool webpack docs

Migrations

Migrate from v7 to v8

useExperimentalSCSSLoader is not used anymore and it will be ignored.

Migrate from v6 to v7

  • In order to keep same config object across all sui tools, sui-bundler config has been moved from package.json root to the config property.
// before
{
  "sui-bundler": { /* config */ }
}

//now
{
  "config": {
    "sui-bundler": { /* config */ }
  }
}
  • As major html-webpack-plugin is being used, if you're using templates on your index.html to access chunks, you must change it to use js property instead chunks.
// before
const {app, vendor} = htmlWebpackPlugin.files.chunks
// now
const {app, vendor} = htmlWebpackPlugin.files.js
  • manualCompression flag on your sui-bundler config is not longer supported and it will be ignored. No more manual compression are featured.

  • scripts config is not longer supported as ScriptExtHtmlWebpackPlugin is not longer used.

  • Deprecated usage of old service-worker based on workbox has been removed.

  • Now, only .js and .json extensions will be resolved if you ignore them on importing the file.

// before
import util from './util' // finally, any extension will be handled as we're using * as a fallback
// after
import util from './util' // only .js and .json files will be resolved
  • externals config has been removed. Stop using externals for loading external scripts and just put your scripts in the src/index.html file or load by importing them in your app.

Contributing

Please refer to the main repo contributing info.

Dependents (3)

Package Sidebar

Install

npm i @s-ui/bundler

Weekly Downloads

2,438

Version

9.57.0

License

MIT

Unpacked Size

79.8 kB

Total Files

39

Last publish

Collaborators

  • daniel.perez.ext
  • albert.peiro
  • frandelacasa-adevinta
  • mariapaula.forero.ext
  • hpintos_adevinta
  • sziauberyte
  • victor.perez.adevinta
  • oscar-raig-adevinta
  • carlos.gonzalezl
  • carolina.mallo.ext
  • david.nieto
  • ferran.simon
  • xavi_conejo
  • sergi.quintela
  • jamile.radloff
  • xavi_ballestar
  • luz_adv
  • ignacio.rodriguez
  • carlosvillu-adevinta
  • diegomr
  • arturo.vicente
  • adria.velardos
  • emiliovz
  • dann41
  • ruben-martin
  • pol.valls
  • cristina.rodriguez.duque
  • sergio.escano
  • marc.benito
  • azahara
  • patricio.sartore
  • giovanny.sayas.ext
  • david.cuadrado.ext
  • alex.castells
  • beatrizip
  • pablo.rey-adevinta
  • sergiocollado
  • mango.sanchezredondo
  • cristhianb
  • alisa_bayanova
  • davidmartin2108
  • ferrangbtw
  • estefania_garcia
  • belen.santos
  • alfredo.arronte
  • joanleon-adv
  • giodelabarrera.adevinta
  • luis-garrido
  • aitor.rodriguez
  • jordi.munoz
  • oscar_ramirez
  • ignacio_navarro
  • a.ferrer
  • gfabregoadv
  • izeller
  • salvador.juan
  • oriol.egea
  • ivanmlaborda
  • alejandro.ferrante
  • pa.chruscinski.ext
  • isabelgomez87
  • jenifer.lopez
  • daniela.aguilera
  • pablogs
  • javier.miguel
  • oscar.gomez
  • marian.lucaci
  • alverd004
  • oriol.puig
  • nacho_torrella
  • xavi.murcia
  • chloe.leteinturier
  • javiauso
  • alfredo.zimperz
  • francisco.ruiz.lloret
  • fermin.adevinta
  • andresadv
  • schibstedspain