This page provides some guidelines on how to handle advanced front-end
topics when sharing a light module.
Using npm to share Magnolia light modules provides great opportunities
to take advantage of the npm dependency resolution, and to incorporate
front-end build processes.
With light development and sharing on npm, Magnolia in no way seeks to
create another front-end framework. The initiative is about making it
easy for authors to include the benefits and innovations in the
front-end frameworks, javascript libraries and web-based services in
their web projects. Our goal is to provide guidelines to the Magnolia
community to ensure that packages are easy-to-understand and use, and
that the developers of packages have complete flexibility in how their
package is built and interacts with the rest of the npm and the
front-end ecosystem.
In this page, we assume:
Your npm package is a ready-to-use light module.
The source control project contains all the information about the
project, but is not necessarily a functional light module.
Running npm run build creates a functional light module.
Each module is responsible for its own build.
Frontend build processes (LESS, SASS, ES6 and so on)
Each module contains its own build pipeline which is run when the
npm run build command is executed. This build pipeline processes the
source files provided in the _dev directory and typically generates
files in the webresources directory.
Magnolia does not recommend any specific build for a module.
This is because there exist many rapidly changing front-end tools. We do
not want to limit users to a single build pipeline at the project level
that all modules would have to adhere to. With a module-level build,
each module has the freedom to select its own build pipeline and is sure
that it will build properly, no matter the project environment.
The npm package.jsonprepublish script should run npm run build so
that the build pipeline will be run whenever the package is published.
This ensures that all packages on npm are always `built' and ready to
use as light modules.
The _dev directory with all its source files, and the build config
files like .babelrc should be excluded from the built npm package.
This is accomplished by listing them in the standard .npmignore file.
As a best practice, consider including any built files in a .gitignore
file. This ensures that devs using the project will get a build based on
the latest versions, eliminates redundancy, and serves to document what
is being generated.
Examples
github.com/magnolia-cms/calculator-magnolia Illustrates
building an ES5 JS file from several ES6 files. It also demonstrates
building css from Less files. It includes the prepublish hook and the
.npmignore file.
npm library dependencies
A light module will often rely on functionality provided by other npm
packages, typically javascript or css. For example, a component that
exposes the features of a js library like chart.js to content authors.
To be DRY, the light module source control project (ie github) should
not include those libraries.
Based on the same module-level build introduced above, a module
should declare those projects as npm dependencies in its
package.json. The build pipeline must include a step to either
generate new resources (js, css, etc) based on those dependencies, or
simply copy resources from those dependencies - and place them in the
webresources directory.
Big popular libraries like jquery and angular should usually not be
brought in via npm dependencies. Since many components are likely to
depend on them, and they are available via CDN, a project developer will
usually prefer to manage those libraries by hand.
Note that it is the modules job to generate/copy the proper resources in
the webresources directory, but not to handle how they get into the web
page. This is left to the project developer so that they can use the web
resources strategy that makes the most sense for their project (resfn,
theme, include, etc).
Testing
A light module can contain unit tests for any custom javascript
functionality using standard js testing frameworks.
To test magnolia rendering, integration tests can easily be provided to
test a demo page for the presence of expected DOM. These tests can be
written with the cheerio library
which leverages jQuery for easily selecting the contents of the html
DOM. For example, a demo page could contain the same component, but
configured via the dialog in 4 different ways. A test could check each
rendered version for expected HTML elements. You could use more
sophisticated approaches than simple DOM tests, such as selenium to test
user interactions with your components.
Tests are especially valuable for open source projects. They make it
easier for people to contribute to your project, because they (and you)
will see if they have broken anything.
Steps to create a test of magnolia rendering (illustrated in the above
project):
Create a demo page with one or more instances of your component
configured in various ways via the dialog.
Export the page as an xml bootstrap file to the _dev/demos
directory.
Supply a test script in _dev/test/integration which loads the demo
webpage and checks the rendered DOM for expected contents. (For example
with the cheerio library.)
Add an integration and test script to the package.json.
Supply a .travis.yml configuration, and connect your git repo to the
free travis-ci continuous integration service.
Light project: Front-end build on the entire project
A light project consists of a package.json file which declares all of
the light modules in the project as npm dependencies, and any required
build pipeline. A light project is an optional concept.
For each shared light module, we recommend a module-level build.
However, on a project level, you may want to further process the
contents of all modules in your project. The most common use case is
that you want to concatenate or minify the web resources from all the
modules into a fewer number of resources. Projects often have only
app.js and styles.css files.
For a light project setup we suggest the following directory structure:
The light-project files at the root of the directory.
A src directory where the project can put the dependencies.
A dist directory where the project will place the processed light
modules. The dist directory functions as your magnolia.resources.dir
directory.
If some of the modules that your project depends on are on your hard
drive instead of npm, you can reference the files directly. Npm then
builds the project (if a prepublish hook is defined) and takes the
.npmignore of the module into account.