Giter VIP home page Giter VIP logo

cli-build-widget's Introduction

@dojo/cli-build-widget

Build Status Build status codecov npm version

The official CLI command for building Dojo custom elements and widget libraries.

Usage

To use @dojo/cli-build-widget in a single project, install the package:

npm install @dojo/cli-build-widget

Features

@dojo/cli-build-widget is an optional command for the @dojo/cli.

By default widgets are built using an evergreen configuration, meaning that the build process:

  • Prefers .mjs modules over .js modules
  • Uses { target: 'es6', module: 'esnext' } Typescript compiler options
  • Elides features based on the chrome flag from dojo/webpack-contrib

Project Structure

A custom elements or library project is expected to have the following directory and file structure:

src/
	custom-element-parent/
		customElementParent.m.css
		CustomElementParent.ts
	custom-element-child/
		customElementChild.m.css
		CustomElementChild.ts
tests/
	unit/
	functional/
.dojorc

Building

@dojo/cli-build-widget can be used to build either custom elements or a library of Dojo widgets. Library builds can be enabled with the --target=lib (or -t lib) flag. While custom element builds aim to provide a minimum set of files required to render an individual custom element in the browser, library builds simply 1) transpile TypeScript to .mjs and legacy .js files, 2) build, minimize, and generate .d.ts and .js files for CSS modules, 3) and copy font and image assets.

When building a Dojo widgets library, any widget that should be included MUST be specified in the --widgets option (see both Widgets and Configuration below). When present, src/main.ts takes precedence.

There are two modes available to build Dojo custom elements or widget libraries: dist and dev. When building custom elements, a test mode is also provided. The mode required can be passed using the --mode flag:

# For custom element builds
dojo build --mode dist

# For library builds
dojo build --mode dist --target lib

The built files are written to the output/{mode selected} directory. The output mirrors the src directory, so if a custom element is located at src/custom-element/CustomElement.s, the built element will be output to output/{mode}/custom-element/CustomElement.js.

Note: dist is the default mode and so can be run without any arguments, dojo build.

Dist Mode

The dist mode creates a production ready build.

Dev mode

The dev mode creates a build that has been optimized for debugging and development.

Test mode

The test mode creates bundles that can be used to run the unit and functional tests for the custom element(s).

Serving An Example Page

A web server can be started with the --serve flag. By default, the build is served on port 9999, but this can be changed with the --port (-p) flag:

# build once and then serve on port 3000
dojo build -s -p 3000

Watching

Building with the --watch option observes the file system for changes, and recompiles to the appropriate output/{dist|dev|test} directory, depending on the current --mode. When used in the conjunction with the --serve option and --mode=dev, --watch=memory can be specified to enable automatic browser updates and hot module replacement (HMR).

dojo build -w # start a file-based watch
dojo build -s -w=memory -m=dev # build to an in-memory file system with HMR

Widgets

The path for widgets to build can be provided using the repeating option --widgets:

dojo build --widgets src/custom-element-child/CustomElementChild --widgets src/custom-element-parent/CustomElementParent

Legacy

To build widgets for legacy environments use the --legacy or -l flag. Widgets built with the legacy flag will need to include the polyfill for the native shim. For library builds, both legacy and evergreen JavaScript files are output side-by-side.

Eject

Ejecting @dojo/cli-build-widget will produce the following files under the config/build-widget directory:

  • build-options.json: the build-specific config options removed from the .dojorc
  • ejected.config.js: the root webpack config that passes the build options to the appropriate mode-specific config based on the --env.mode flag's value.
  • base.config.js: a common configuration used by the mode-specific configs.
  • dev.config.js: the configuration used during development.
  • dist.config.js: the production configuration.
  • test.config.js: the configuration used when running tests.
  • template/custom-element.js: A template that registers custom elements

As already noted, the dojorc's build-widget options are moved to config/build-widget/build-options.json after ejecting. Further, the modes are specified using webpack's env flag (e.g., --env.mode=dev), defaulting to dist. You can run a build using webpack with:

node_modules/.bin/webpack --config=config/build-widget/ejected.config.js --env.mode={dev|dist|test}

Configuration

Custom element/widget library projects use a .dojorc file at the project root to control various aspects of development such as testing and building. This file is required to build the project, it MUST be valid JSON, and for widget projects it MUST provide at least a widgets array with the widget paths. All other values are options. The following options can be used beneath the "build-widget" key:

widgets: string[]

Contains paths relative to the project root to the widgets that should be built.

{
	"build-widget": {
		"widgets": [
			"src/menu-item/MenuItem",
			"src/menu/Menu"
		]
	}
}

bundles: object

Useful for breaking a build into smaller bundles, the bundles option is a map of webpack bundle names to arrays of modules that should be bundled together. For example, with the following configuration both src/Foo and src/Bar will be grouped in the foo.[hash].js bundle:

{
	"build-widget": {
		"bundles": {
			"foo": [
				"src/Foo",
				"src/Bar"
			]
		}
	}
}

features: object

A map of has features to boolean flags that can be used when building in dist mode to remove unneeded imports or conditional branches. See the static-build-loader documentation for more information.

How do I contribute?

We appreciate your interest! Please see the Dojo Meta Repository for the Contributing Guidelines. This repository uses prettier for code style and is configured with a pre-commit hook to automatically fix formatting issues on staged .ts files before performing the commit.

Installation

To start working with this package, clone the repository and run:

npm install

In order to build the project, you can run all the build steps via:

npm run build

Scripts

watch

Will run a watcher process which looks for changes in the source code TypeScript files and runs the build scripts to update the contents of the built files in dist with latest changes made.

clean

Runs the clean up script which removes any built files like output, dist, coverage which get created on build and testing steps.

lint

Runs the ts-lint and prettier on all .ts files in the src and tests directories. ts-lint will ensure that all linting rules have been abided by and prettier will fix any detected code style violations in the code.

Testing

Test cases MUST be written using Intern using the BDD test interface and Assert assertion interface.

90% branch coverage MUST be provided for all code submitted to this repository, as reported by istanbul’s combined coverage results for all supported platforms.

The command is tested by running via the Dojo CLI and asserting the build output against known fixtures. To do this, a test artifact needs to be built and installed into the test-app:

npm test

Testing

Test cases MUST be written using Intern using the BDD test interface and Assert assertion interface.

90% branch coverage MUST be provided for all code submitted to this repository, as reported by istanbul’s combined coverage results for all supported platforms.

The command is tested by running via the Dojo CLI and asserting the build output against known fixtures. To do this, a test artifact needs to be built and installed into the test-app:

npm test

Once the test artifact has been installed, if there have been no changes to the command code grunt test can be used to repeat the tests.

Licensing information

© 2019 JS Foundation. New BSD license.

cli-build-widget's People

Contributors

agubler avatar bryanforbes avatar jameslmilner avatar maier49 avatar matt-gadd avatar mwistrand avatar nicknisi avatar rorticus avatar tomdye avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cli-build-widget's Issues

Enums are not available when running non-legacy build

When running non-legacy build on a widget that imports an enum such as Keys from @dojo/widgets/common/util the build will fail / warn that Keys cannot be found.

The enum is present in the .d.ts file, but does not feature in the .js or the .m.js in the widget dist.

Use Cypress for functional tests

@dojo/cli-build-app switched from using fixtures to using Cypress for its functional tests, and @dojo/cli-build-widget ought to do the same.

Upgrade to use @dojo/framework

Specifically, The following dependencies need to be replaced with @dojo/framework

  • core
  • has
  • i18n
  • widget-core
  • routing
  • stores
  • shim.

Build pulls in Dojo theme font files with bogus absolute paths

If a widget built with dojo build --target lib uses the Dojo Select widget, the build pulls in font files from the Dojo theme CSS, adding them to the output with bogus absolute paths.

These files should not be pulled in at all, as nothing in the source or output references them.

Example output:

$ dojo build widget --target lib

ℹ cli-build-widget: 1.0.0
ℹ typescript: 3.4.5
✔ hash: f509775dccfa74b71f49
✖ errors: 0
⚠ warnings: 0

chunks:

assets:
augmentedvideo/AugmentedVideo.d.ts (1.14kb)
augmentedvideo/AugmentedVideo.mjs (3.95kb)
augmentedvideo/AugmentedVideo.mjs.map (8.03kb)
augmentedvideo/Overlay.d.ts (0.17kb)
augmentedvideo/Overlay.mjs (0.06kb)
augmentedvideo/Overlay.mjs.map (0.56kb)
augmentedvideo/augmentedVideo.m.css (0.18kb)
augmentedvideo/augmentedVideo.m.css.d.ts (0.06kb)
augmentedvideo/augmentedVideo.m.css.js (0.16kb)
augmentedvideo/augmentedVideo.m.css.map (0.38kb)
augmentedvideooptions/AugmentedVideoOptions.d.ts (0.78kb)
augmentedvideooptions/AugmentedVideoOptions.mjs (2.08kb)
augmentedvideooptions/AugmentedVideoOptions.mjs.map (4.16kb)
augmentedvideooptions/augmentedVideoOptions.m.css (0.12kb)
augmentedvideooptions/augmentedVideoOptions.m.css.d.ts (0.14kb)
augmentedvideooptions/augmentedVideoOptions.m.css.js (0.33kb)
augmentedvideooptions/augmentedVideoOptions.m.css.map (0.34kb)
home/rob/repos/user_interfaces/widgets/ea_dojo_video/node_modules/@dojo/widgets/theme/fonts/dojo2.svg (15.75kb)
home/rob/repos/user_interfaces/widgets/ea_dojo_video/node_modules/@dojo/widgets/theme/fonts/dojo2.ttf (5.04kb)
home/rob/repos/user_interfaces/widgets/ea_dojo_video/node_modules/@dojo/widgets/theme/fonts/dojo2.woff (5.11kb)
output at: file:////home/rob/repos/user_interfaces/widgets/ea_dojo_video/output/dist

The build completed successfully.

Build-widget doesn't handle css from dependencies

I'm having a headache trying to get functional widgets to build using the 'cli-build-widget' plugin/tool
if I run 'dojo build widget' I get a css related compile error.

./node_modules/@dojo/widgets/theme/icon.m.css
Module build failed (from 
./node_modules/@dojo/cli-build-widget/node_modules/mini-css-extract-plugin/dist/
loader.js):
ModuleParseError: Module parse failed: Unexpected character '' (1:0)
You may need an appropriate loader to handle this file type.
(Source code omitted for this binary file)
    at handleParseError 
(/home/nathan/projects/user_interfaces/test/node_modules/webpack/lib/NormalModul
e.js:432:19)...

(the widget compiles normally and unit tests run fine)
I've created a codesandbox, however I can't reproduce the error there https://codesandbox.io/s/wizardly-https-vxnql

Dojo build widget command only output the last one widget when widgets that in different folders has the same name

bug

In https://github.com/xiaohulu/cli-build-widget-demo, there are two widgets with the same name but place at different folders, like below:

image

The two widgets are all config at .dojorc

{
	"build-widget": {
		"widgets": [
			"src/a/MyWidget.tsx",
			"src/b/MyWidget.tsx"
		]
	}
}

Then run dojo build widget --mode dist --target lib, the build result only contains output/dist/b/MyWidget.*, not contains /a/MyWidget.* files.

image

The code place at https://github.com/xiaohulu/cli-build-widget-demo.

Version: 6.0.2

Thanks!

The image is packaged but corrupted in some way during the build

There is a a.jpg image at assets folder.

Then I require a.jpg at Home.ts

const png1 = require("../assets/a.jpg");
const factory = create();

export default factory(function Profile() {
	return v('h1', { classes: [css.root] }, [
		'Home Page',
		v('img', {src: png1})
	]);
});

then run npm run build(dojo build widget --mode dist --target lib) to build a dojo library, build success, but a.jpg can not open.

demo https://github.com/xiaohulu/dojo-picture

Library build issues with @dojo/widgets

Bug

Package Version: 6.0.0-alpha.2

Code

@dojo/widgets

OS: Windows 10

Branch: https://github.com/KaneFreeman/widgets/tree/select-dynamic-positioning

Expected behavior:

Running command npm run release -- --release=6.0.0-alpha.6 --next=6.0.0-pre --dry-run --skip-checks, which utilizes the library build should produce a usable build.

Actual behavior:

The build has the following issues:

  • .tsx files are being compiled, but not having their extension renamed. Manually changing the extension of the output files to .js fixes the issue.
  • The source map paths are wrong. The source map and file are in the same folder, but the parent folder name is being added.
    • Example: /*# sourceMappingURL=\text-input\index.js.map*/
    • The following error occurs when using it in a build (with cli-build-app).
      (Emitted value instead of an instance of Error) Cannot find SourceMap '\text-input\index.js.map': Error: Can't resolve './\text-input\index.js.map' in '[root_dir]\node_modules\@dojo\widgets\text-input'
      NonErrorEmittedError: (Emitted value instead of an instance of Error) Cannot find SourceMap '\text-input\index.js.map': Error: Can't resolve './\text-input\index.js.map' in '[root_dir]\node_modules\@dojo\widgets\text-input'
      
    • Changing the source map urls to /*# sourceMappingURL=\index.js.map*/ fixes the issue.

Combining both manual fixes produces a working build.

dojo build command throws error in Node 10

The following error is thrown when running dojo build on Node 10.

node[54694]: ../src/node_file.cc:829:void node::fs::Stat(const FunctionCallbackInfo<v8::Value> &): Assertion `(argc) == (3)' failed.
 1: node::Abort() [/usr/local/bin/node]
 2: node::Assert(char const* const (*) [4]) [/usr/local/bin/node]
 3: node::fs::LStat(v8::FunctionCallbackInfo<v8::Value> const&) [/usr/local/bin/node]
 4: v8::internal::FunctionCallbackArguments::Call(v8::internal::CallHandlerInfo*) [/usr/local/bin/node]
 5: v8::internal::MaybeHandle<v8::internal::Object> v8::internal::(anonymous namespace)::HandleApiCallHelper<false>(v8::internal::Isolate*, v8::internal::Handle<v8::internal::HeapObject>, v8::internal::Handle<v8::internal::HeapObject>, v8::internal::Handle<v8::internal::FunctionTemplateInfo>, v8::internal::Handle<v8::internal::Object>, v8::internal::BuiltinArguments) [/usr/local/bin/node]
 6: v8::internal::Builtin_Impl_HandleApiCall(v8::internal::BuiltinArguments, v8::internal::Isolate*) [/usr/local/bin/node]
 7: 0x1a00db98427d

This occurs for both dojo build commands. The app is tracked at dojo/cli-build-app#93.

Support new target for building a widget library

Currently cli-build-widget has a single target, which is to compile a dojo widget into a custom element.

We should look to add a new "target" for building a widget library that can be be shared across multiple downstream projects. This needs to include building the widgets (to .mjs and .js), css and provide the widget typings files.

Possible example usage:

dojo build widget --target lib

Add type checking to build widget

Currently type checking is disabled for cli-build-widget as it uses too much memory when building multiple custom elements.

We should look to see if any existing plugins (for example fork-ts-checker-webpack-plugin) can provide us with the type checking needed without consuming too many system resources.

Can not import function-based widget which was build with cli-build-widget

I create a function-based widget at "src/PageDesigner.ts"

import { v, create } from '@dojo/framework/core/vdom';

import * as css from './styles/PageDesigner.m.css';

const factory = create();

export default factory(function PageDesigner() {
	return v('h1', { classes: [css.root] }, ['Page Designer']);
});

and add it to .dojorc

{
	"build-widget": {
		"widgets": [
			"src/PageDesigner.ts"
		]
	}
}

then run dojo build widget --mode dist --target lib

Then generate 3 files at output/dist

  • PageDesigner.d.ts
  • PageDesigner.mjs
  • PageDesigner.mjs.map

But the dist file content is

PageDesigner.d.ts

declare const _default: import("@dojo/framework/core/interfaces").WNodeFactory<{
    properties: import("@dojo/framework/core/interfaces").WidgetProperties;
    children: import("@dojo/framework/core/interfaces").DNode<any>[];
}>;
export default _default;

Not export default PageDesigner
So I can not import the PageDesigner widget.

The demo git repo is https://github.com/blocklang/page-designer.git

Dev mode obfuscates class names

With cli-build-app, dev mode gives readable class names in both the node and the stylesheet. This is not the case with cli-build-widget.

Use the same css module ident for all builds

We currently have a more verbose ident for dev that includes the filename, this causes problems when writing functional tests as the selectors change between modes, and the test bundle (which would contain the target selectors) currently uses the dist selectors.

Their is no harm in using the more verbose ident for all modes as the bundle size after gzip or related compression is likely no different.

Related to dojo/cli-build-app#154

Upgrade to Webpack 4

As the title says, upgrade to webpack 4. May need changes in webpack-contrib.

When has one widget, index.d.ts was generated to the root folder

I have a dojo project which has one widget

src
    page
        index.tsx
        index.m.css
        index.m.css.d.ts
.dojorc
package.json

then run dojo build widget --mode dist --target lib, the generate files are

output
    dist
        index.d.ts
        page
            index.mjs
            index.mjs.map
            ...

then I import the Page in another project, throw errors.

// Module not found: Error: Can't resolve 'project1' in 'xx\project1\src\page'
import Page from 'project1';
// can not wirte to below, because the page folder not contain `*.d.ts`
import Page from 'project1/page';

the index.d.ts should be in page folder, not in the root folder.

Note:If has two widgets, the output is right

Ship evergreen builds by default

At the moment we have to specifically target an evergreen browser to get a build that elides a lot of stuff that is now in all browsers - apart from IE11. We should flip this so we ship an evergreen bundle by default, and offer a legacy flag to build for IE11.

Process for creating user widget libraries

Finalise and document the process for developing custom widget libraries.

Ideally with a tutorial describing how to...

  • create a new widget library project from scratch
  • build using dojo build widget, including css and other resources
  • use an unpublished widget library package in a Dojo application using npm link or similar

Make sure loader resolution defaults to the scope of this package

Bug
Currently the behaviour of the loader resolution in webpack defaults to the root of the project, which means if you have 2 webpack related commands installed (say cli-build-widget), it can and up resolving to the wrong loaders from the other package (depending on how it's deduped by npm). To fix we should always resolve from the node_modules in this package first then the project node_modules.

resolveLoader: {
    modules: [path.resolve(__dirname, 'node_modules'), 'node_modules'],
}

Build Web Components with a shared bundle

It would be incredibly useful if I the widget build could support building multiple web components in a project and output a shared bundle to limit the total size of the components.

Right now if I have multiple elements in my .dojorc like this.

{
  "build-widget": {
    "elements": [
      "src/widgets/DatePicker",
      "src/widgets/Authentication",
      "src/widgets/Profile"
    ]
  }
}

Each output web component contains it's own widget source, but also all the dojo code needed as well in its bundle.

It would be really useful if we could build the whole project of web components to use a shared common.js file of the dojo code used. I assume it could work the way webpack dynamically loads files at runtime to load the common file as needed per web component. This helps cut down on the total size of js transferred.

The real benefit here is that at this point dojo could be used a source for building scalable web component libraries that could be used across multiple projects, regardless of the technology or framework being used by developers.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.