Skip to content

Latest commit

 

History

History
414 lines (297 loc) · 17.9 KB

README.md

File metadata and controls

414 lines (297 loc) · 17.9 KB

component-build-tools

A set of build tools to help in the creation of components. These components can be web components or any other grouping of code to be used in the browser or in other environments like node.js.

Used with rollup, these tools will allow you to process locale file and template files into a set of .mjs files that are importable in your script files.

For those of you that have used gulp-component-assembler these tools allow similar functionality but by using ES6 imports instead of defining the component through an assembly.json file.

Install

You need to install the component build tools in your project:

npm install --save-dev component-build-tools

You will also need to install the latest rollup in your project

npm install --save-dev rollup

Usage

Config file

For the component-build-tools to work with rollup you need to provide a config file named rollup.config.js in your project's root folder.

Here are two sample rollup.config.js files:

const rollup = require('component-build-tools').components.rollup;

const config = {
  buildTypes: [ rollup.BUILD_TYPES.MJS ], // Set this to any build styles you want.
  srcFolders: ['assets/wc-n1', 'assets/wc-p3'] // Set this to any folder you want to have rollup process
};

module.exports = rollup.init(config);

and

const {init, BUILD_TYPES} = require('component-build-tools').components.rollup;

const config = {
  buildTypes: [ BUILD_TYPES.MJS, BUILD_TYPES.CJS, BUILD_TYPES.CJS5 ],
  srcFolders: ['assets/*']
};

module.exports = init(config);

The first example will only build from the folders assets/wc-n1 and assets/wc-p3 and will generate two output module files in the dist/js folder.

The second example builds module files, common JS files and common JS files that have been transpiled into ES5. Its source is any and all folders inside the assets folder.

Run

To run rollup:

./node_modules/.bin/rollup -c

Options

BUILD Styles

There are 5 build styles:

Build Style Description
IIFE IFFE styled output with no transpiling.
IIFE5 IFFE output with ES5 transpile operation. For compatibility with older ES5 browsers.
CJS Common JS output. Load by using require
CJS5 Common JS output with ES5 transpile. Load by using require. For compatibility with older ES5 browsers.
MJS ES6 Module output. Load by using import

Config options

When you call init you pass in a set of options. Most are optional. The only one required is srcFolders.

Option Type Default Value Description
addEOLocale bool true Add the EO (Esperanto) locale if it does not exist.
addKELocale bool false Add the KE locale if it does not exist. This is a fake locale that returns the KEY as the string to help in debugging.
alwaysReturnFile bool false The files _compiled/locales.msj and _compiled/templates.mjs will always be created if this value is true. Otherwise they will not be created.
buildTypes array [
  BUILD_TYPES.MJS,
  BUILD_TYPES.IIFE
]
The list of build styles to create. See Build Styles above.
debug bool false true to enable debug output.
defaultLocale string 'en' The locale to use as the default locale when compiling locale files.
defaultLocaleVariable string 'document.documentElement.lang' The variable to use as the default locale that is read at runtime that your app defines.
document.documentElement.lang is the value stored in the lang attribute of the <html> tag. Changing that value will change what locale strings are used.
<html lang='en'> will use the 'en' locale strings.
<html lang="fr"> will use the 'fr' locale strings.
distPath string/object 'dist/js' Path into which the distribution files will be placed.
If distPath is an object then it must include one entry per output type defined in buildTypes.
See distPath below.
includePath bool false If this is set to false then the output files are placed directly into the distPath folder. If this is set to true then the output files are placed in a child folder named after the source folder inside the distPath folder.
localeFiles array ['locales/strings_*.json'] An array of relative glob paths defining the locale files to load.
makeMinFiles bool false If set to true then the output will include creating minimized files.
minTemplateWS bool true Minimize the white space within the template files.
separateByLocale bool false Currently not supported When true this will generate one output file per locale supported in the localesFile glob list. false will only produce one file with all locale data embedded.
sourcemap bool false If true then sourcemap files are generated. If false then sourcemap files are not generated.
srcFileName string undefined If undefined then we use the folder name to specify the source file name. Otherwise the srcFileName string is used.
See srcFileName below.
srcFolders string/array [] An array of glob folders in which to look into for source files.
This is required. The user must supply this value.
See srcFolders below.
tagMissingStrings bool true When true Mark missing locale strings so they are easily seen.
templateFiles array ['*.html'] A glob array of files to include as templates.
tempLocalesName string 'locales.mjs' The filename used for the compiled locales file.
tempPath string './_compiled/' The path into which all compiled files are place.
tempTemplateName string 'templates.mjs' The filename used for the compiled templates file.
useStrict bool false If true then add "use strict" at the top of the rolled up output files.

distPath

If distPath is a string then the same distPath is used in the output for any build type.

You can also define distPath as an object to change the output path for each build type.

If you set buildType to [BUILD_TYPES.MJS, BUILD_TYPES.CJS] then your distPath object needs to include two properties, one per build type:

distPath: {
  MJS: './path/for/mjs/built/files',
  CJS: './cjs/file/path'
}

If you include extra properties they will be ignored. But you must include one property per build type. If you don't then an exception will be thrown and the build will fail.

srcFileName

If srcFileName is left as undefined then the name of the source files will be the same name as the folder with the extension of .mjs.

For example, the file structure below shows a folder named test1 and within it is a file named test1.mjs. The build process of the build tools will take test1.mjs as the root file to use in the rollup config file.

└─ components
   └─ test1
      ├─ test1.msj
      ├─ style.html
      └─ content.html

And the default output file will be placed in:

└─ dist
   └─ js
      └─ test1.mjs

The output file ./dist/js/test1/test1.mjs will combine the two template files style.html and content.html as well as the source file test1.js as one set of code.

If srcFileName were set to index.mjs then the build tools would use index.msj as the root file to use in the rollup config file.

└─ components
   └─ test1
      ├─ index.msj
      ├─ style.html
      └─ content.html

would still produce the same output structure of:

└─ dist
   └─ js
      └─ test1.mjs

If the value for includePath had been set to true then the output structure would be:

└─ dist
   └─ js
      └─ test1
         └─ test1.mjs

srcFolders

srcFolders is the only option that must be supplied. This specifies the folder or folders that are to be processed by the build tools.

If you have all of your components stored in child folders of the folder ./comps then you would call init({srcFolders:['./comps/*']}).

Every folder directly under ./comps would get processed. Any subfolder that was found to match the requirements of a component will be handed off to rollup for further processing.

You can specify each folder independently within the array, and each entry in the array can either be a real path to a specific folder or a glob path to a set of folders.

init({srcFolders:['./comps/component1']}) will only look at the path ./comps/component1 while init({srcFolders:['./comps/*']}) will look at all direct child folders under ./comps.

Locale files

Locale files are JSON files that contain locale specific translations of strings you use in your application. By default the files are all placed in the locales folder and are named strings_??.json where the ?? is the 2 letter locale such as en, fr, or ja.

The file ./locales/strings_en.json will contain the English version of the strings. The file ./locales/strings_fr.json contains the French version of the strings. You can use things like en-US for US english and fr-CA for Canadian French. The two letter ISO 639-1 code and a subset of the BCP-47 codes are supported.

Currently we only support the 2 letter ISO 639-1 code and this ISO 639-1 code followed by a dash "-" and then the 2 letter ISO-3166 country code. Like en, fr, en-US, en-GB, fr-CA and fr-FR. Case is ignored.

ISO-3166 Country Codes and ISO-639 Language Codes

These locale files are combined into the file ./_compiled/locales.mjs and you access them by importing that file and then calling the default function to get the set of locale strings for the specified locale.

import locales from "./_compiled/locales.mjs";
const lang = locales('en');

If no locale key is provided in the locales() function then the default locale object is returned.

Templates

Template files tend to be HTML files but can be any kind of file. As a result of the compile process the contents of the template files are embedded into a template literal inside of the template.mjs file.

For example, if there is a template file called person.html:

<div class="person">
  <div>Name: <span class="name">Frank N Stein</span></div>
</div>

Then the entry generated in the templates.mjs file would be:

case 'person':
  return `<div class="person"> <div>Name: <span class="name">Frank N Stein</span></div> </div>`;

The back-tick: ```

Since all templates become ES6 Template literals you can do some creative things in your template files. Let's say that you want to create a <table> with 5 rows. You could do it like this:

<table>
  <tr class="row1">
    <td>1</td>
    <td class="name"></td>
    <td class="age"></td>
  </tr>
  <tr class="row2">
    <td>1</td>
    <td class="name"></td>
    <td class="age"></td>
  </tr>
  <tr class="row3">
    <td>3</td>
    <td class="name"></td>
    <td class="age"></td>
  </tr>
  <tr class="row4">
    <td>4</td>
    <td class="name"></td>
    <td class="age"></td>
  </tr>
  <tr class="row5">
    <td>5</td>
    <td class="name"></td>
    <td class="age"></td>
  </tr>
</table>

Or you can embed an second ES6 template literal within your template:

<table>
  ${[1,2,3,4,5].map( i => `<tr class="row${i}">
    <td>${i}</td>
    <td class="name"></td>
    <td class="age"></td>
  </tr>`).join('')}
</table>

When you get this string it will execute this template literal expression:

[1,2,3,4,5].map( i => `<tr class="row${i}">
  <td>${i}</td>
  <td class="name"></td>
  <td class="age"></td>
</tr>`).join('')

This, in turn will return five copies of the internal HTML (The <tr> with its three <td> tags). THe join('') will convert them into a string and this will be inserted just inside the <table> tags.

The end result of the two example above are almost identical. Since we removed the duplication of code the second example is more flexible and less prone to errors.


Escaping the back-tick

If you need to add a back-tick ``` character into your template, outside of your template literals, then you must escape it like with the backslash, like this:

<p>This is the back-tick: \`</p>

This allows the back-tick to exist as a stand alone character and not as the ending of the generated template literal.

The compiled output would be this:

return `<p>This is the back-tick: \`</p>`;

Using locale strings in templates

If your component includes both templates and locale strings then the strings are made available to the template through the lang variable. The lang variable is auto-inserted into the templates.mjs file for all projects that have locale string files.

Locale file: ./locales/strings_en.json

{
  "NAME": "Frank N Stein"
}

Template file: ./person.html

<div class="person">
  <div>Name: <span class="name">${lang.NAME}</span></div>
</div>

Output in ./_compiled/templates.mjs:

import locales from './locales.mjs';
const lang = locales();
.
.
.

templates.str = function(key, data) {
  switch(key) {
    case 'person';
      return `<div class="person"> <div>Name: <span class="name">${lang.NAME}</span></div> </div>`;
    .
    .
    .
  }
}

Passing data into a template

The signature of the functions templates.str and templates.dom is:

function(key, data) {}

So when your code calls either templates.str and templates.dom you can pass any object as the second parameter.

The first parameter is they key used to get the correct template.

If you wanted to create a table with a number of rows defined by a variable you would create your template like this:

Template file content.html:

<table>
  ${[...Array(data.size).keys()].map( i => `<tr class="row${i}">
    <td>${i}</td>
    <td class="name"></td>
    <td class="age"></td>
  </tr>`).join('')}
</table>

If you called templates.str('content', {size: 10}) then 10 rows would be created. If you called templates.str('content', {size: 87}) then 87 rows would be created.

You can pass in any data and use it any way your imagination can imagine. You just need to follow the rules for template literals.

Adding an import in a template

Sometimes you need to be able to access external code within a template.

In this example we need an external function called name.

<div class="person">
  <div>Name: <span class="name">${name("FRANK")}</span></div>
</div>

To do this we can add the import to the template file like this:

<%
import name from "../name.mjs";
%>
<div class="person">
  <div>Name: <span class="name">${name("FRANK")}</span></div>
</div>

The import line of code will be inserted into the top of templates.mjs. You can add as many import lines as you need.

ONLY import is valid within a template. No other code is permitted.

History

Date Version Description
07/24/2018 2.1.1 ● Fixed tests to run on Windows as well as other OSs.
● Handle windows path.join() with inclusion of drive letter: C:\
● Revert to simple minification if html-minify fails.
● Updated version and docs
06/18/2018 2.1.0 ● Moved source files to lib folder.
● Added index.js.
● Added use of html-minify to improve minification of templates.
● Cleaned up documentation.
● Now using components.rollup as a sub-object for require. Getting ready for v3.0.0 and additional functionality.
06/11/2018 2.0.1 ● Bug fix to correctly set the name of an IIFE conversion.
06/07/2018 2.0.0 Breaking Changes!!
● Removed the escaping of the back-tick in templates. This was preventing sub-ES6 Template Literals in the templates.
● You now must list the source folders. In most cases you would change from srcPath: "modules/src" to srcPath: "modules/src/*"
● Changed default build types from MJS and IIFE to MJS and CJS since these can both be loaded in a similar manner.
addKELocale is now false by default
alwaysReturnFile is now false by default.
defaultLocaleVariable is now set to document.documentElement.lang which is the value set in the lang attribute of the <html> tag: <html lang="fr"> would use fr as the default value when getting the lang object.
includePath is now false by default.
● New config options dstExtCJS, dstExtCJS5, dstExtIIFE, dstExtIIFE5 and dstExtMJS allow you to set the output extension for the various output file types.
● Added ability for distPath to be an object and not just a string.
● Added and cleaned up Docs
● Added more testing for the new code.
05/29/2018 1.1.0 ● Added code to allow template files to define imports they need.
● Improved Docs. Added Travis and Code Climate.
05/10/2018 1.0.2 ● Corrected REGEX to get correct file names for locale files.
● Improved error output to simplify debugging.
04/03/2018 1.0.1 ● Added pre-commit tests.
03/29/2018 1.0.0 ● Added options for addKELocale, defaultLocaleVariable and sourcemap.
● Spelling Correction: Renamed option minTempalteWS to minTemplateWS.
● If there are no compiled files to generate and alwaysReturnFile if set to false then no temporary folder is created.
02/26/2018 0.0.0 Initial Release.