
Research
Malicious npm Packages Impersonate Flashbots SDKs, Targeting Ethereum Wallet Credentials
Four npm packages disguised as cryptographic tools steal developer credentials and send them to attacker-controlled Telegram infrastructure.
reduce-web-component
Advanced tools
Features
browserify
and depsify
to pack scripts and styles into common shared bundles.watchify2
to watch file changes, addition and deletion.postcss
to preprocess styles by default.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 require
d,
the corresponding style entry should also be @import
ed.
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.
The hello
page
page/hello/index.js
)module.exports = 'hello, ' + require('world')
page/hello/index.css
).hello {}
The hi
page
page/hi/index.js
)module.exports = 'hi, ' + require('earth')
null
)The world
component
node_modules/world/index.js
)module.exports = 'world'
node_modules/world/index.css
).world {
color: red;
}
The earth
component
node_modules/earth/index.js
)module.exports = 'earth'
node_modules/earth/index.css
).earth {
color: blue;
}
The original dependency graph looks like:
The dependency graph we want for bundling should look like:
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).
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
.
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)))
})
Check the configure file.
Scripts are bundled with browserify
.
So, plugins and transforms can be applied during the build process.
Check browserify-handbook
for more information.
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 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'
}
},
}
}
FAQs
Pack js and css files in web components
The npm package reduce-web-component receives a total of 2 weekly downloads. As such, reduce-web-component popularity was classified as not popular.
We found that reduce-web-component demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 3 open source maintainers collaborating on the project.
Did you know?
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.
Research
Four npm packages disguised as cryptographic tools steal developer credentials and send them to attacker-controlled Telegram infrastructure.
Security News
Ruby maintainers from Bundler and rbenv teams are building rv to bring Python uv's speed and unified tooling approach to Ruby development.
Security News
Following last week’s supply chain attack, Nx published findings on the GitHub Actions exploit and moved npm publishing to Trusted Publishers.