@webruntime/compiler
TypeScript icon, indicating that this package has built-in type declarations

1.61.4 • Public • Published

Lightning Web Runtime :: Compiler

Table of contents

Introduction

The Lightning Web Runtime Compiler is a pluggable Rollup-based bundler for off-core LWC-based applications.

The Web Runtime Compiler extends the LWC/Rollup bundling functionality with the ability to inject container services, which can then participate in the compilation lifecycle phase.

Background

Definitions

Lightning Web Runtime: A LWC application runtime.

container: Initializes and builds the set of container services which make up an application.

container service: A service plugin, which can be (1) addressed and (2) hook into various container lifecycle phases.

specifier: A string import value (eg: import('app/home'), import('lodash')).

pivot: A way to specify when a particular component/module may be loaded relative to some context (eg: 'mobile' vs 'desktop', locale, etc).

Rollup plugins

Along with custom plugins, these Rollup plugins are automatically included and used by the Compiler:

APIs

compile()

The Web Runtime Compiler exposes one main function:

async function compile(input):Promise<output>

It takes in a configuration object, and returns a Promise to its output.

Compiler input

  • LWC compiler options:

    • name (string, required): component name.
    • namespace (string, required): component namespace.
    • files ({ string: string, ...}, required): key/value pairs where each key is a file path and its value is a string containing the file contents.
    • baseDir (string, optional, default = ""): a directory prefix which contains contains the components being compiled.
    • lwcOptions (object, optional): pass in a customized LWC Rollup plugin config object, which gets merged with a default object. The following options are available (all are optional): rootDir, modules, exclude, stylesheetConfig, and experimentalDynamicComponent.
    • outputConfig (object[], optional):
      • compat (boolean, optional, default = false): true indicates browser compatibility mode.
      • minify (boolean, optional, default = false): true if the bundle should be minified.
      • sourcemap (boolean, optional, default = false): true if a source map should be generated.
      • env (object, optional, default = { NODE_ENV: 'development' }):
        • NODE_ENV (string, required) = node environment string (eg: 'production', 'development', etc).
  • Rollup options:

    • input (string, optional, default = ${namespace}/${name}): the input path for the bundle, similar to Rollup's input.
    • external (string[], optional, default =['lwc']): list of dependencies that should not be included in the bundled output, similar to Rollup's external.
    • format (string, optional, default = 'amd'): type of output ('amd', 'cjs', 'esm', 'iife', 'umd') similar to Rollup's output.format.
    • formatConfig (object, optional, default = { id: namespace + '/' + name, define: undefined }):
      • amd (object):
        • define (string): function to use in place of define, similar to Rollup's output.amd.define
  • Web Runtime options:

    • plugins (Plugin[], optional, default = []): array of Rollup plugins to use.
    • inlineConfig (object[], optional, default = []): describes the exclusion patterns for each module descriptor; array of objects with the following properites:
      • descriptor (string, required): specifier which should have all dependencies inlined, EXCEPT for those in the exclude array. Globs are supported.
      • exclude (string[], optional, default = []): array of specifiers which should be excluded from being inlined. Globs are supported. Globstars can be used to recursively match all modules in scoped namespaces or nested namespaces. Excluded specifiers that are not listed in external or exposedModules will be inlined.
    • exposedModules (string[], optional, default: []): array of specifiers that are supported by the Web Runtime container.

Compiler output

The Compiler's output uses the same format as the LWC compiler.

  • output (object):
    • success (boolean): true if the Compiler encountered no fatal errors.
    • diagnostics (CompilerDiagnostic[]): array of error and warning information.
    • result:
      • code (string): the resulting bundled code.
      • map (* | null): the generated source map, if requested.
      • outputConfig (object | undefined): same object passed in as [Compiler input](#compiler-input).outputConfig.
    • version (string): the version of the Compiler which bundled this code.

Examples

Simple application

Creating a bundle for an LWC application. Components are stored in ./src.

All dependencies except for lwc will be inlined in the bundle.

import { compile } from '@webruntime/compiler';
import * as path from 'path';

const options = {
    name: 'main',
    namespace: 'any',
    external: ['lwc'],
    baseDir: path.join(__dirname, 'src'),
    files: {
        'any/main': `
            import { createElement } from 'lwc';
            import App from 'x/app';
            const element = createElement('x-app', { is: App });
            document.body.appendChild(element);
        `,
        'x/app': `
            export default 'Hello World';
        `,
    },
};

const { success, diagnostics } = await compile(options);

if (!success) {
    for (let diagnostic of diagnostics) {
        console.error(`${diagnostic.level}: ${diagnostic.message}`);
    }
}

// Compiled Result:
// define('any/main', ['lwc'], function (lwc) { 'use strict';\n" +
//       '\n' +
//       "        var App = 'Hello World';\n" +
//       '\n' +
//       "        const element = lwc.createElement('x-app', {\n" +
//       '          is: App\n' +
//       '        });\n' +
//       '        document.body.appendChild(element);\n' +
//       '\n' +
//       '});\n',

Simple application with inline config

Create a bundle for an LWC application without inlining any dependencies. Components are stored in ./src.

All dependencies except for lwc will be defined separetly in the bundle.

import { compile } from '@webruntime/compiler';
import * as path from 'path';

const options = {
    name: 'main',
    namespace: 'any',
    external: ['lwc'],
    baseDir: path.join(__dirname, 'src'),
    files: {
        'any/main': `
            import { createElement } from 'lwc';
            import App from 'x/app';
            const element = createElement('x-app', { is: App });
            document.body.appendChild(element);
        `,
        'x/app': `
            export default 'Hello World';
        `,
    },
    inlineConfig: [
        {
            descriptor: '*/*',
            exclude: ['*/*'],
        },
    ],
};

const { success, diagnostics } = await compile(options);

if (!success) {
    for (let diagnostic of diagnostics) {
        console.error(`${diagnostic.level}: ${diagnostic.message}`);
    }
}

// Compiled Result:
// define('any/main', ['lwc', 'x/app'], function (lwc, App) { 'use strict';\n" +
//       '\n' +
//       "            App = App && Object.prototype.hasOwnProperty.call(App, 'default') ? App['default'] : App;\n" +
//       '\n' +
//       "            const element = lwc.createElement('x-app', {\n" +
//       '              is: App\n' +
//       '            });\n' +
//       '            document.body.appendChild(element);\n' +
//       '\n' +
//       '});\n',

LWC

Creating a bundle for a LWC stored in the files object:

import { compile } from '@webruntime/compiler';

const options = {
    name: 'lwc',
    namespace: 'my',
    external: ['lwc'],
    files: {
        'my/lwc.js': `
            import { LightningElement } from 'lwc';
            export default class Lwc extends LightningElement {}
        `,
        'my/lwc.html': '<template>lwc</template>',
        'my/lwc.css': ':host { font-size: 16px; }',
    },
};

const { success, code } = await compile(options);

console.log('The bundle is: ', success ? code : 'a failure');

// Output:
// The bundle is: define('my/lwc', ['lwc'], function (lwc) { ... });

JavaScript library

Create a non-LWC bundle. The JavaScript entry point must live in the files object:

import { compile } from '@webruntime/compiler';
import * as fs from 'fs';
import * as path from 'path';

const filePath = path.join(__dirname, 'src', 'x', 'file.js');
const fileContents = fs.readFileSync(filePath).toString();
export const options = {
    name: 'file',
    namespace: '',
    files: {
        'file.js': fileContents,
    },
};

const { code = '' } = await compile(options);
export default code;

Full Compiler config object

{
    // LWC
    name: 'cmp',
    input: 'x',
    files: {
        'logger.js': 'export const logger = console.log;'
    },
    baseDir: path.join(__dirname, 'apps'),
    lwcOptions: {
        stylesheetConfig: {
            customProperties: {
                resolution: {
                    type: 'module',
                    name: '@salesforce/cssvars/customProperties',
                },
            },
        },
        experimentalDynamicComponent: {
            loader: '',
            strictSpecifier: true,
        },
    },
    outputConfig: {
        compat: true,
        minify: true,
        sourcemap: true,
        env: { NODE_ENV: 'production' }
    },

    // Rollup
    external: [
        'lwc',
        'force/lds',
        'wire-service'
    ],
    format: 'amd',
    formatConfig: {
        amd: { define: 'loader.addModule' }
    },

    // Web Runtime
    plugins: [
        {
            plugin: 'src/rollup/global-rollup.js',
            config: {
                globals: {
                    'lodash': '_',
                },
            },
        },
    ],
    inlineConfig: [
       { descriptor: 'view/*', exclude: ['view/faq', 'wire-service'] },
       { descriptor: 'x/foo', exclude: ['@salesforce/**'] }
    ],
}

Container config mappings

Compiler configuration options are gathered from different areas, including:

  • the calling service, possibly via a Rollup plugin (service)
  • the Container config object (containerConfig)
name: service
namespace: service
files: service
baseDir: containerConfig.moduleDir
stylesheetConfig: service or containerConfig.compilerConfig.lwcOptions
experimentalDynamicComponent: service or containerConfig.compilerConfig.lwcOptions
outputConfig: containerConfig.compilerConfig.outputConfig[mode]
external: containerConfig.externals, containerConfig.preloadModules, compilerConfig.external and exclusionsFrom(config.bundle)
format: service or container defaults
formatConfig: containerConfig.compilerConfig.formatConfig
plugins: service or container defaults
inlineConfig: containerConfig.bundle

Readme

Keywords

none

Package Sidebar

Install

npm i @webruntime/compiler

Weekly Downloads

439

Version

1.61.4

License

MIT

Unpacked Size

351 kB

Total Files

49

Last publish

Collaborators

  • tconn
  • diervo
  • zhawtof
  • kjkimsfdc
  • lwc-admin