Sharing light modules - advanced topics
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.json
prepublish
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.
- Examples
-
-
github.com/magnolia-cms/chartjs-magnolia Illustrates a very simple build pipeline, it just copies the js file that it depends on from the chartjs package.
-
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.
- Example
-
-
github.com/magnolia-cms/calculator-magnolia Illustrates unit and integration tests which are automatically run on the https://travis-ci.org/ service whenever a
git push
is made on the repository. Travis build status for this project: https://travis-ci.org/magnolia-cms/calculator-magnolia
-
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 thecheerio
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.
Additional details: Testing Light Modules for Frontend Developers
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. Thedist
directory functions as yourmagnolia.resources.dir
directory.
Clean | Built |
---|---|
Examples:
-
github.com/magnolia-cms/light-project-example-gulp A light project builder based on Gulp
-
github.com/magnolia-cms/light-project-example-webpack A light project builder based on Webpack
Local modules
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.
"dependencies": { "calculator-magnolia": "../[whatever-path-on-filesystem/]calculator-magnolia" }