Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

reduce-web-component

Package Overview
Dependencies
Maintainers
3
Versions
15
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

reduce-web-component

Pack js and css files in web components

  • 0.8.0
  • latest
  • Source
  • npm
  • Socket score

Version published
Maintainers
3
Created
Source

reduce-web-component

version status coverage dependencies devDependencies node

Features

Example

Suppose we put pages under the directory /path/to/src/page, and other components under /path/to/src/node_modules.

A page or component may have a style entry as well as a script entry. For simplicity, entries are named as index.[js|css] if present.

There are two pages (hello and hi), as well as two components (world, earth).

The hello page will present the world component (both scripts and styles needed). We can do this by adding require('world') in hello/index.js, and @import "world"; in hello/index.css. However, if world is no longer needed, we have to remove both require('world') and @import "world", which is really cumbersome.

So, we decide that if the script entry is required, the corresponding style entry should also be @imported. In such cases, we say the component is required. This is achieved by adding style dependencies according to script dependencies.

Eventually, we want scripts required by all pages to be packed into /path/to/build/bundle.js, and styles into /path/to/build/bundle.css.

We can use this package to do that.

Input

The hello page

  • Script entry (page/hello/index.js)
module.exports = 'hello, ' + require('world')

  • Style entry (page/hello/index.css)
.hello {}

The hi page

  • Script entry (page/hi/index.js)
module.exports = 'hi, ' + require('earth')

  • Style entry (null)

The world component

  • Script entry (node_modules/world/index.js)
module.exports = 'world'

  • Style entry (node_modules/world/index.css)
.world {
  color: red;
}

The earth component

  • Script entry (node_modules/earth/index.js)
module.exports = 'earth'

  • Style entry (node_modules/earth/index.css)
.earth {
  color: blue;
}

The original dependency graph looks like:

native dependency graph

The dependency graph we want for bundling should look like:

component dependency graph

NOTE As hi requires earth and earth is shipped with styles, hi will need styles at last. So a virtual hi/index.css is created (but not written into disk).

Output

We run the following script to bundle js and css:

'use strict'

const path = require('path')
const reduce = require('reduce-web-component')

const options = {
  getStyle: function (jsFile) {
    return path.dirname(jsFile) + '/index.css'
  },

  reduce: {
    basedir: path.resolve(__dirname, 'src'),
  },

  on: {
    log: console.log.bind(console),
    error: function (err) {
      console.error(err.stack)
    },
    'reduce.end': function (bytes, duration) {
      console.log(
        '[%s done] %d bytes written (%d seconds)',
        this._type, bytes, (duration / 1000).toFixed(2)
      )
    },
  },

  js: {
    entries: 'page/**/index.js',
    bundleOptions: 'bundle.js',
    dest: 'build',
  },

  css: {
    // No need to specify entries,
    // because we have done that implicitly by setting getStyle.
    // entries: 'page/**/index.css',
    bundleOptions: 'bundle.css',
    dest: 'build',
  },
}

reduce.bundle(options).then(() => console.log('DONE'))


Besides hello/index.css and world/index.css, earth/index.css will also be included in bundle.css.

Usage

const reduce = require('reduce-web-component')

// pack
reduce.bundle(options).then(() => {})

// watch mode
reduce.watch(options).on('done', () => {})

To work with gulp:

const gulp = require('gulp')
const reduce = require('reduce-web-component')

gulp.task('build', () => {
  return reduce.bundle(options)
})
gulp.task('watch', function (cb) {
  reduce.watch(options)
    .on('close', cb)
    .on('done', () => console.log('-'.repeat(40)))
})

Common shared bundles

Check the configure file.

Browserify

Scripts are bundled with browserify. So, plugins and transforms can be applied during the build process.

Check browserify-handbook for more information.

PostCss

Styles are preprocessed with postcss. Check reduce-css-postcss to see the default processors.

depsify is used to bundle styles, so that styles can be packed into common shared multiple bundles.

options

Options for both JS and CSS bundling are configurable.

Check reduce-js and reduce-css for the following options:

  • entries. Type: String, Array. Optional Globs to locate entries.
  • reduce. Type: Object. Options passed to browserify or depsify.
  • bundleOptions. Type: Object. Options passed to common-bundle.
  • dest. Type: String, Array. Options passed to [b.dest].
  • watch. Type: Object. Options passed to watchify2.

Other options:

  • on. Type: Object. Listeners to be added to the bundler instance.
  • plugin. Plugins to process the vinyl stream. They are just like gulp plugins.

Example:

{
  js: { 
    entries: 'page/**/index.js',
    reduce: { basedir: '/path/to/src' },
    bundleOptions: {
      groups: 'page/**/index.js',
      common: 'common.js',
    },
    watch: {
      ignoreWatch: ['**/node_modules/**'],
      entryGlob: 'page/**/index.js',
    },
    on: { 
      'common.map': o => {},
      error: console.log,
    }
  },
  css: {
    entries: 'page/**/index.css',
    reduce: { basedir: '/path/to/src' },
    bundleOptions: { groups: 'page/**/index.css', common: 'common.css' },
    watch: {
      ignoreWatch: ['**/node_modules/**'],
      entryGlob: 'page/**/index.css',
    },
    on: { 
      error: console.log,
    }
  },
}

Meanwhile, we have:

  • getStyle: bind JS and CSS together so that when js is required, the corresponding css will also be imported implicitly by the dependant's css.
{ 
  getStyle: jsFile => { 
    return path.dirname(jsFile) + '/index.css'
  },
  js: {},
  css: {},
}

Suppose there are /path/to/component/x/index.js and /path/to/component/y/index.js, and their binding CSS are /path/to/component/x/index.css and /path/to/component/y/index.css respectively.

If we require('../y') in x/index.js, then CSS will be bundled as if there is @external "../y"; in x/index.css.

Common options for both options.js and options.css could also be specified as properties of options:

{
  // common options
  reduce: { basedir: '/path/to/src' },
  on: { 
    error: console.log,
  },

  js: { 
    entries: 'page/**/index.js',
    bundleOptions: {
      groups: 'page/**/index.js',
      common: 'common.js',
    },
    watch: {
      ignoreWatch: ['**/node_modules/**'],
      entryGlob: 'page/**/index.js',
    },
    on: { 
      'common.map': o => {},
    }
  },
  css: {
    entries: 'page/**/index.css',
    bundleOptions: { groups: 'page/**/index.css', common: 'common.css' },
    watch: {
      ignoreWatch: ['**/node_modules/**'],
      entryGlob: 'page/**/index.css',
    },
  },
}

Environment-specific options are possible:

{
  reduce: { basedir: '/path/to/src' },
  on: { 
    error: console.log,
  },

  js: { 
    entries: 'page/**/index.js',
    bundleOptions: {
      groups: 'page/**/index.js',
      common: 'common.js',
    },
    watch: {
      ignoreWatch: ['**/node_modules/**'],
      entryGlob: 'page/**/index.js',
    },
    on: { 
      'common.map': o => {},
    }
  },
  css: {
    entries: 'page/**/index.css',
    bundleOptions: { groups: 'page/**/index.css', common: 'common.css' },
    watch: {
      ignoreWatch: ['**/node_modules/**'],
      entryGlob: 'page/**/index.css',
    },
  },
  env: { 
    development: { 
      js: { 
        reduce: { 
          plugin: ['index-hashify', 'browserify-hmr']
        },
      }
    },
    production: { 
      js: { 
        plugin: 'gulp-uglify'
      },
      css: { 
        plugin: 'gulp-uglifycss'
      }
    },
  }
}

Keywords

FAQs

Package last updated on 12 Jun 2016

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc