
Security News
Static vs. Runtime Reachability: Insights from Latio’s On the Record Podcast
The Latio podcast explores how static and runtime reachability help teams prioritize exploitable vulnerabilities and streamline AppSec workflows.
This npm-module is a builder for SPA BEM projects. It has a lot of options and does the following:
Just try to read all the material and construct in your head the vision how it works.
What does mean BEM project? It means, that files are located like in the tree below:
root/
- - components/
- - - - w-app/
- - - - - - elem/
- - - - - - - - elem.html
- - - - - - - - elem_color_red.styl
- - - - - - w-app.deps.json
- - - - - - w-app.html
- - - - - - w-app.js
- - - - - - w-app_disabled.js
- - - - - - w-app_size_big.styl
- - scripts/
- - - - jquery/
- - - - - - jquery.js
As you can see the project has the strong file structure:
Let's analyze a filename components/w-app/elem/elem_color_red:en.deps.json
:
components
is a categorie's name;w-app
is a block's name;elem
is an elem's name;color
is a modifier's name;red
is a modifier's value;en
is a language;deps.json
is a so-called file's technology;json
is a file's extension.All files of the project should be named according with these rules.
Blocks, which name starts with
p-
(pages) orw-
(wrappers) are called entry points. Its are roots of module's dependencies. Typical names for entry points arep-profile
,p-info
,w-app
orw-landing
.
When pages, wrappers and languages intersect each other, we get exit points. Exit points are independent and gobem builds files of each one. Typical names for exit points are
components/p-info+components/w-app:
orcomponents/w-app+components/w-app:en
.
Build process is independent for each exit point! The amount of output files could be calculated as:
(files) = (wrappers) * (pages) * (langs) * (deps) * (techs)
Of course the real number is less, because not all files exist.
Module is an abstract entity: block, element or modifier. For example this is a module's path: components/w-app/elem
.
If gobem has configuration with three languages and three technologies:
config.buildLangs = ['', 'ru', 'en'];
config.buildTechs = ['js', 'css', 'html'];
then 1 module will be mapped with 9 files:
The client-side architecture of any well-designed single page application consists of the following block's types:
w-
)p-
)s-
)b-
)type | is singleton | is entry point |
---|---|---|
w- | yes | yes |
p- | no | yes |
s- | yes | no |
b- | no | no |
Here are described all configurable parameters for gobem npm-module. Containing them object should be passed to gobem.configure(config)
.
This function is called each time before rebuilding. It gets two arguments: next
and config
. An example given:
config.beforeBuilding = function (next, config) {
let filePath = path.join(config.rootDir, 'file.txt');
fs.readFile(filePath, 'utf-8', (error, content) => {
app.setFileContent(content);
next(error);
});
};
This function is the same as beforeBuilding()
, but called after each rebuilding.
Root directory should be an absolute path to the folder, containing project files.
Output directory should be a relative path to the folder, where resulting files will be saved. By default is equal output
.
An array of instructions, which will be executed during each rebuilding. Each instruction is an array too, which contains a name of a processor and arguments for a function-constructor. Example given:
config.buildInstructions = [
['select', 0, /\.js$/],
['write', 1]
];
If you have a complicated project, probably you want to use constructor function instead an array. gobem allows it.
config.buildInstructions = function (exitPointName) {
return [
['select', 0, /\.js$/],
['write', 1]
];
};
If you want to exclude some folders or files from your project, point this fact here. All paths should be relative. If you have only one file to exclude, string could be passed.
This is a technology of files, which contain exhaustive information about dependencies. By default is deps.json
.
An array of the languages, which should be built. By default is ['']
(only not localized files will be built).
An array of the technologies, which should be built. By default is []
(nothing will be built).
An array of the technologies, which should be loaded in the memory. By default is equal to buildTechs
(all technologies will be loaded). Not loaded files is processed too, but their content is equal null
. You are able to load ones by your preferred way inside a processor.
This feature is needed, for example, to prevent loading *.node.js files (usually we use require
to connect npm-modules).
This number is an upper time limit of the build process (in seconds). Default value is 60
seconds. 0
means there is no limit.
This boolean flag says, that gobem should clear previous output, before start writing the current one. Default value is true
.
This boolean flag says, that gobem should overwrite existing files. If true
all files are stored to the same folder, if false
then files are divided into directories by exit points.
For example:
// overwriteOutput == false
// (each exit point has own files)
output
- - components^w-app+components^w-app:
- - - - components
- - - - scripts
- - components^p-page+components^w-app:
- - - - components
// overwriteOutput == true
// (files of all exit points are merged)
output
- - components
- - scripts
If you use SPDY or HTTP2, it is preferable set overwriteOutput
to true
. But be careful: if several exit points have files with the same path and different content, it will be available only one version.
Triggers rebuilding, when any project's file have been changed. By default is false
.
This is a list of files, where all paths are relative. If a file from the list is changed, rebuilding is triggered. By default it's empty array []
. In case with one file could be a string.
For example, you can add in this array build.js
(module, which constructs buildInstructions
) and rebuild your project immediately after build instructions have been changed.
The time in seconds between two successful rebuldings. Default value is 0
, what means that the project aren't rebuilt by timer.
The time in seconds between two attempts of the rebuilding in case of an error. Default value is 20
seconds.
This method configures gobem, runs a timer for rebuilding (if one exists), starts watching the files.
Note that gobem.configure()
don't trigger rebuilding. It is recommended to call gobem.build()
immediately after configuration.
Builds a project, using the last configuration. Usually this method is called automatically.
Returns a promise. Resolve function gets an array with files of the required exit point. If error occured in the build process, promise will be rejected with error gobem.status()
.
Resets gobem to initial state. This method is always called before the configuration.
Returns an error, that occured in the build process. If a project has built successfully, null
will be returned.
Processor is an entity, which gets one file's map and returns another one. The most of processor's methods have the same arguments:
input.get('components/w-app/elem/elem.js');
output.set(filePath, '"use strict";\n' + fileContent);
Each processor is a separate npm-module. This module should export a factory-function, which returns required processor. The factory gets arguments from buildInstructions
, it's executed in the special context, which has some additional information. An example given how to create the empty processor:
module.exports = function (arg1, arg2) {
// this.config - initial config
// this.modules - all modules of the current project
// this.exitPoint - the name of the building exit point
return {};
};
This method is called before processing (once per exit point).
This method is called for each file of a current exit point. Pay attention, that path
always is a string with file's path, but content
could be different.
content
is undefined
.buildLoaders
, content
will be equal null
(it means gobem even didn't try to load file).This method is called only after successful processing (once per exit point).
This method is always called after processing has finished (once per exit point). Its goal to release using resources.
An array buildInstructions
says to gobem how to build each exit point. It means gobem applies the same instructions to each exit point.
Each instruction from this array contains as the first argument the name of the processor, which should be used. Except processors, installed in the directory node_modules
, you are able to use some internal processors. Usually they work with virtual storages.
What are virtual storages? 0-storage is read-only, it's source files of exit point. Then gobem copies files from one storage to another, processes ones, clears some storages and finally gets output - resulting files. But what is the output? It is the storage with a maximal id.
Obligatorily see an example in the end of section, how buildInstructions
work! Below are described all internal processors of gobem:
Copies files, whose paths satisfy the regular expression regexp
, from the storage
to the buffer. By default regexp
is .*
, that means all files are matched.
Writes all files from the buffer to the storage
.
Deletes all files of the storage
.
Passes exit point name, iterable keys and values to callback
(3 arguments in the sum). If exitPointName
is specified, then this processor works only for one exit point.
Calls callback function with a single argument - the name of a current exit point.
// abstract example of an array with build instructions
config.buildInstructions = [
['select', 0, /^[^.]+\.lib\.js$/],
['gobem-proc-js-minify'],
['write', 1],
['select', 0, /^[^.]+\.es6\.js$/],
['gobem-proc-babel'],
['write', 1],
['select', 1],
['gobem-proc-wrap-script'],
['write', 2],
['clear', 1],
['select', 0, /^[^.]+\.lib\.css$/],
['write', 1],
['select', 0, /^[^.]+\.styl$/],
['debug', (exitPointName, keys) => console.log(Array.from(keys)), 'modules/w-app+modules/w-app:'],
['gobem-proc-stylus'],
['write', 1],
['select', 1],
['gobem-proc-css-minify'],
['write', 2],
['call', function (exitPointName) {
global.counter++;
}]
];
// storage 2 is an output
To describe dependencies between modules, it is used deps.json
technology. Below is how to specify dependencies, using this format:
/* w-app.deps.json */
{
"components": [
"_size_big",
"__border",
"_color_red",
"b-block",
"_disabled"
],
"scripts": ["jquery"],
"services": ["timer", "ajax"]
}
/* will be transformed to the following modules */
components/w-app_size_big
components/w-app/border
components/w-app/border_color_red
components/b-block
components/b-block_disabled
scripts/jquery
services/timer
services/ajax
Here is a repository, which can help you to understand, how it works.
FAQs
A builder for BEM projects.
We found that gobem demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer 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.
Security News
The Latio podcast explores how static and runtime reachability help teams prioritize exploitable vulnerabilities and streamline AppSec workflows.
Security News
The latest Opengrep releases add Apex scanning, precision rule tuning, and performance gains for open source static code analysis.
Security News
npm now supports Trusted Publishing with OIDC, enabling secure package publishing directly from CI/CD workflows without relying on long-lived tokens.