Code Monkey home page Code Monkey logo

cli-build-webpack's Introduction

@dojo/cli-build-webpack

WARNING This package is deprecated in favor of functionality found elsewhere in Dojo 2 (@dojo/cli-build-app and @dojo/cli-build-widget). This package is not being further developed at this time as its feature set is redundant with other capabilities.

Build Status Build status codecov npm version

Usage

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

npm install @dojo/cli-build-webpack

to use @dojo/cli-build-webpack in every project, install the project globally:

npm install -g @dojo/cli-build-webpack

Features

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

Building

To build a Dojo 2 application for publishing:

dojo build webpack

This command will output the built files to the dist directory. After running this command, you can open the dist/index.html file to see your application.

You can also build in watch mode, which will automatically rebuild your application when it changes:

dojo build webpack -w

When using watch mode, you can specify a port, or port range, to use when determining which port to serve your application on.

# a single port
dojo build webpack -w --port=8080

# a list of ports
dojo build webpack -w --port=8080,8181

# a range of ports
dojo build webpack -w --port=9010:9000

The watch server will use the first unused port in the list you specified. Default port range is 9990-9999.

@dojo/cli-build-webpack can be customized further. Use the help option to see everything you can do:

dojo build webpack --help

Building a custom element

@dojo/cli-build-webpack can also build custom web elements as per the custom web v1 specification. Custom elements are built by providing the name of a custom element descriptor.

dojo build webpack --element=src/path/to/createTheSpecialElement.ts

This will output a dist/the-special directory containing:

  • the-special.js - JavaScript file containing code specific to the TheSpecial widget.
  • widget-core.js - JavaScript file containing shared widget code. This is separated to allow for better caching by the browser.
  • the-special.css - CSS relating to the TheSpecial widget.
  • the-special.html - HTML import file that will import all the scripts and styles needed to use the element.

If the source file does not follow the pattern create[custom element]Element, @dojo/cli-build-webpack cannot determine what the name of the custom element should be. In this case, you can specify the --elementPrefix option to explicitly name the element.

dojo build webpack --element=src/path/to/element.ts --elementPrefix=the-special

Feature optimization

This command supports the ability to optimize code based on statically asserted features. The tool can search the source code for modules that attempt to detect features using a @dojo/has type of API. By supplying a feature set (or sets) on the command line, the build will optimize code branches, making the code smaller and more efficient. This allows targeting of particular platforms.

When specifying multiple feature sets, if they do not align, the tool will not optimize the source code for these feature sets and will instead continue to leave that feature to be detected at run-time.

From the command line, the feature sets are provided to the -f or --feature argument. The available feature sets are aligned to platforms. The currently available feature sets are:

Feature Set Description
android This feature set represents Android 5+ with integrated Chrome browser. Note it is not suitable for Android 4.4.
chrome This feature set represents Chrome 59+ or Opera 46+1
edge This feature set represents Edge 15+1
firefox This feature set represents Firefox 54+1
ie11 This feature set represents Internet Explorer 11
ios This feature set represents iOS 10.3+2
node This feature set represents Node.js 6/72
node8 This feature set represents Node.js 8+
safari This feature set represents Safari 10+2

[1]: Many of these features were present in earlier versions, but the specific version was the GA release at the time of writing when this was validated.

[2]: At least one of the features was not present in previous releases.

Instead of sniffing for a browser, the feature sets are a static set of features that are expressed as flags in the @dojo modules. The current set of flags are:

Flag Description
arraybuffer Supports ArrayBuffer
blob Supports the blob response type for XHR requests
dom-mutationobserver Supports MutationObserver
es-observable Supports ES Observable proposal
es2017-object Supports ES2017 Object features
es2017-string Supports ES2017 String features
es6-array Supports ES2015 Array features (except .fill)
es6-array-fill Supports a non-buggy version of Array.prototype.fill()
es6-map Supports ES2015 Map
es6-math Supports ES2015 Math features (except .imul
es6-math-imul Supports a non-buggy version of Math.imul()
es6-object Supports ES2015 Object features
es6-promise Supports ES2015 Promise
es6-set Supports ES2015 Set
es6-string Supports ES2015 String features (except .raw()
es6-string-raw Supports a non-buggy version of String.raw()
es6-symbol Supports ES2015 Symbol
es6-weakmap Supports ES2015 WeakMap
es7-array Supports ES2016 Array features
fetch Supports the fetch API
filereader Supports the FileReader API
float32array Supports the Float32Array API
formdata Supports form data
host-node Is a NodeJS Host
host-browser Is a Browser Host
microtasks Supports an API that allows scheduling of microtasks
node-buffer Supports the Node.JS Buffer API
raf Supports the requestAnimationFrame API
setimmediate Supports the setImmediate API
xhr Supports XMLHTTPRequest API
xhr2 Supports the XMLHTTPRequest 2 API

An example of generating a build that hardwires features for Microsoft Edge and Chrome, you would use the following on the command line:

$ dojo build -f edge chrome

Eject

Ejecting @dojo/cli-build-webpack will produce a config/build-webpack/webpack.config.js file. You can run build using webpack with:

node_modules/.bin/webpack --config=config/build-webpack/webpack.config.js

Interop with external libraries

External libraries that cannot be loaded normally via webpack can be included in a Dojo 2 application by providing an implementation of require or define, and some configuration in the project's .dojorc file. .dojorc is a JSON file that contains configuration for Dojo 2 CLI tasks. Configuration for the dojo build task can be provided under the build-webpack property. Configuration for external dependencies can be provided under the externals property of the build-webpack config. externals is an object with two allowed properties:

  • outputPath: An optional property specifying an output path to which files should be copied.

  • dependencies: A required array that defines which modules should be loaded via the external loader, and what files should be included in the build. Each entry can be one of two types:

  • A string that indicates that this path, and any children of this path, should be loaded via the external loader

  • An object that provides additional configuration for dependencies that need to be copied into the built application. This object has the following properties:

Property Type optional Description
from string false A path relative to node_modules specifying the dependency location to copy into the build application.
to string true A path that replaces from as the location to copy this dependency to. By default, dependencies will be copied to ${externalsOutputPath}/${to} or ${externalsOutputPath}/${from} if to is not specified.
name string true Indicates that this path, and any children of this path, should be loaded via the external loader
inject string, string[], or boolean true This property indicates that this dependency defines, or includes, scripts or stylesheets that should be loaded on the page. If inject is set to true, then the file at the location specified by to or from will be loaded on the page. If this dependency is a folder, then inject can be set to a string or array of strings to define one or more files to inject. Each path in inject should be relative to ${externalsOutputPath}/${to} or ${externalsOutputPath}/${from} depending on whether to was provided.

As an example the following configuration will inject src/legacy/layer.js into the application page, declare that modules a, b, and c are external and should be delegated to the external layer, and then copy the folder node_modules/legacy-dep, from which several files are injected. All of these files will be copied into the externals folder, which could be overridden by specifying the outputPath property in the externals configuration.

"externals": {
   "dependencies": [
       "a",
       "b",
       "c",
       { "from": "src/legacy/layer.js", "inject": true },
       { "from": "node_modules/legacy-dep", "inject": [ "modulA/layer.js", "moduleA/layer.css", "moduleB/layer.js" ] }
   ]
}

Types for any dependencies included in externals can be installed in node_modules/@types, like any other dependency.

How do I contribute?

We appreciate your interest! Please see the Dojo 2 Meta Repository for the Contributing Guidelines and Style Guide.

Installation

To start working with this package, clone the repository and run npm install.

In order to build the project run grunt dev or grunt dist.

Testing

Test cases MUST be written using Intern using the Object 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.

To test locally in node run:

grunt test

Licensing information

ยฉ 2017 JS Foundation. New BSD license.

cli-build-webpack's People

Contributors

agubler avatar bitpshr avatar bryanforbes avatar dylans avatar edhager avatar jdonaghue avatar kitsonk avatar lelit avatar maier49 avatar matt-gadd avatar nicknisi avatar rishson avatar rorticus avatar stdavis avatar tomdye avatar

Stargazers

 avatar  avatar  avatar  avatar

Watchers

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

cli-build-webpack's Issues

The bundle analyser report only supports a single bundle

Bug

cli-build now supports auto and manually defined bundles, but the bundle analyser only supports a single bundle outputting the last created bundle only.

The analyser should support multiple bundles and create a report/reports that reflect them.

Invocation of `Compilation#buildModule()` is wrong for Webpack 2

The API for Compilation#buildModule() changed in Webpack 2 and InjectModulesPlugin was not updated to accommodate this change. Currently, the following is done:

compilation.buildModule(module, (error?: Error) => {

But it should be called like so:

compilation.buildModule(module, false, null, null, (error?: Error) => {

I discovered this while writing typings for Webpack for #53.

Optimize CSS output for dist builds

Enhancement

We currently do not apply any CSS optimization to our build output so we have some duplicated classes (due to css-module composition) and unused variable blocks as well as whitespace and non-shorthand style definitions.
Adding the optimize-css-assets-webpack-plugin webpack plugin for dist builds will achieve this for us.

Example code

...includeWhen(!args.watch && !args.withTests, (args) => {
   return [new OptimizeCssAssetsPlugin()( options )];
}),

Type the WebPack config

Now we're moving the WebPack config over to TypeScript, we should make an effort to properly type it.

Only TypeScript-specific UMD wrappers are ignored

Bug

dojo/cli-build uses a loader that forces the AMD portion of UMD wrappers to be skipped, but it is specific to the UMD wrappers generated by TypeScript (specifically by searching for the presence of var v = factory(require, exports); if (v !== undefined) module.exports = v;. As such, the build still chokes on UMD modules with different wrappers.

Package Version: All versions, including alpha.6

Code

// The following UMD wrapper is correctly bypassed
(function (dependencies, factory) {
    if (typeof module === 'object' && typeof module.exports === 'object') {
        var v = factory(require, exports); if (v !== undefined) module.exports = v;
    }
    else if (typeof define === 'function' && define.amd) {
        define(dependencies, factory);
    }
})(["require", "exports"], function (require, exports) {});

// The following UMD wrapper is not bypassed
(function(global, factory) {
	if ( typeof define === 'function' && define.amd ) {
		define([], factory);
	} else if ( typeof exports === 'object') {
		module.exports = factory();
	}
}( this, function() {});

Update i18n to alpha.6

Enhancement

With @dojo/[email protected], we can remove cldr-data as a dependency. This also includes updating the i18n plugin to extract arrays of URLs passed to @dojo/i18n/cldr/load.default. As with use of @dojo/i18n, users will be required to provide their own CLDR data, but at the same time are not required to include it if their application does not need it.

With this update, users will be able to load CLDR data as follows:

import loadCldrData from '@dojo/i18n/cldr/data';

loadCldrData([
	'cldr-data/main/{locale}/currencies.json',
	'cldr-data/main/{locale}/numbers.json',
	'cldr-data/supplemental/currencyData.json',
	'cldr-data/supplemental/likelySubtags.json',
	'cldr-data/supplemental/numberingSystems.json',
	'cldr-data/supplemental/ordinals.json',
	'cldr-data/supplemental/plurals.json'
]);

At build time, the URLs will be extracted and loaded, and any URL with a {locale} token will be loaded for both the defaultLocale as well as any supportedLocales.

build command is pulling in `cli-build-webpack` modules before project's modules

Bug

It looks like the build command is pulling in it's own node_modules ahead of the projects modules.

Situtation:

When testing cli build with the kitchen sink, I was running into an issue where the wrong @dojo/core was being pulled in. The project looked like this:

<project>
    node_modules/@dojo/core (version alpha.26)
    node_modules/@dojo/cli-build-webpack/node_modules/@dojo/core (version alpha.25)

Upon doing a dojo build, core alpha.25 was being included in the bundle, rather than alpha.26.

--watch does not always recompile unit tests

Bug

When using --watch, the test source files are not always recompiled when they should.

Steps to reproduce:

  1. Create an app: dojo create --name test
  2. From the app directory, start the build: dojo build --watch.
  3. Rename src/App.ts to src/App1.ts.
  4. Notice the build watcher recompiles src/main.ts and tests/unit/App.ts and reports errors.
  5. Edit tests/unit/App.ts and change the failing import statement to
    import App from './../../src/App1';
  6. Notice no recompile occurs.
  7. Edit src/main.ts and fix the import statement.
  8. A recompile occurs but it still reports an error in tests/unit/App.ts even though the code had been updated.
  9. Stop the build watch command and rerun it.
  10. No compile errors.

Should the build watch command be compiling the test source files at all? I am not going to answer that question. But if there are cases when it is going to compile the files and report errors, then it needs to recompile them when I fix the errors.

Allow app-level config for basic overrides/input.

While updates to the webpack configuration itself should and will be handled by the eject command (dojo/cli#44), certain options justify an application-level config. For example, the user should be able to set the application's default locale and any supported locales. As such, the build process should check for the existence of something like path.join(process.cwd(), 'dojo.config.js') and read any values it needs to feed into the configuration.

Passing extra commands to webpack

Would it be possible to find a way to pass additional arguments to webpack? In particular it might be handy to be able to pass the --json argument to be able to generate webpack stats for analysis. With the zero configuration nature of the CLI it become challenging to figure out how to get webpack to run standalone.

Support automatic lazy widget bundling

Enhancement

When using @dojo/core/load to lazy load a module, we want automatically add the module to its own bundle

Given,

registry.define('my-widget', () => {
    return load(require, './MyWidget')
        .then(([ MyWidget ]) => MyWidget.default);
});

We want cli-build to add MyWidget to it's own bundle using something like,

require(`bundle-loader?lazy&name=${widgetName}!./Widget`);

Consider renaming this repo and the published package to 'cli-build-app'

It has been the source of some confusion that the repo is called cli-build but the package is called cli-build-webpack.

I think we should isolate ourselves from a specific implementation (in this case webpack) and rename the repo to cli-build-app and use this name for the published package.

Implement i18n into build process

@rishson commented on Tue Oct 04 2016

Refs dojo/meta#55


@mwistrand commented on Sat Oct 29 2016

Since dojo-i18n allows multiple locales to be used simultaneously and for locale data to be loaded dynamically, the main obstacle to incorporating dojo-i18n into the build process is ensuring that the CLDR data and locale messages are loaded only once.

The CLDR data are loaded via dojo-core/request and then cached locally, and the locale messages are loaded via dojo-core/load and then cached locally. Since the locale messages are proper modules, theoretically they should pose no problem since the build will have already loaded them. The CLDR data, however, are JSON files. As such, pointing to the appropriate cache in both development and production is a more difficult problem. One solution is to write an additional module that converts the CLDR JSON files pulled from unicode.org into UMD modules, so that they can be imported by dojo-core/load and cached by the underlying loader.

With regard to webpack, @matt-gadd, @agubler, @tomdye, and I had discussed using globalize-webpack-plugin, but found that doing so would require changes to the dojo-i18n message structure and would mean loading CLDR and message data twice in development.

Whichever solution we settle on, the following are still required:

  1. A default locale.
  2. An array of locales that should be included in the final build. Any default locale that has been specified will be assumed and not required in this list.
  3. An array of paths to bundle directories. Any files found under ${path}/{locale}/ (where {locale} is one of the locales listed in no. 2 above) will be included in the build.
  4. All CLDR data for the locales listed in no. 2 above are included in the build.
  5. It should still be possible to dynamically load any other CLDR data or messages for locales not explicitly included in the list of supported locales.

Assume `src/` directory prefix in message bundle paths.

Enhancement

When building an application with localized message bundles, the bundlePath specified by the default bundle must be the full path from the current working directory. However, since it is assumed that all application source will be included in the src/ directory, it would be nice if that root directory were assumed by the build. That would allow message bundles to specify their bundle paths without that root directory. For example, a bundle at src/nls/common.ts could specify its bundlePath as just nls/common instead of as src/nls/common.

External CSS

Enhancement

The current webpack config internalizes the css into the js bundle. This although cuts down on network requests, causes a flicker of unstyled content on page load, as well as increasing the size of the bundle.

Preserve state when using --watch

Enhancement

Currently, when using the watch flag (dojo build webpack --watch) the application's state is disposed of whenever a change is made. This reduces the usefulness of the watch feature when working on a use-case that requires the application to be in a certain state to get to the feature that is being worked on.

This enhancement is intended to either modify the behavior of the watch command to preserve state or, optionally, add another flag that would allow state to be maintained.

Support dynamic locale data loading

Enhancement

The build is capable of including all data for a set list of locales, and applications can switch between those locales at runtime, but it would useful to also provide a means of building other locale data into separate webpack chunks so that they can be loaded dynamically. For example, if I have an application that supports English and Spanish by default, but I also want to localize my application for French speakers without incorporating that additional data into the main build, it would still be possible to retrieve all French messages and CLDR data via an additional HTTP request.

Friendlier error message if you run multiple build-with-watch

If you run multiple dojo build -w then you'll get:

$ dojo build -w
events.js:160
      throw er; // Unhandled 'error' event
      ^

Error: listen EADDRINUSE 127.0.0.1:9999
    at Object.exports._errnoException (util.js:1022:11)
    at exports._exceptionWithHostPort (util.js:1045:20)
    at Server._listen2 (net.js:1262:14)
    at listen (net.js:1298:10)
    at doListening (net.js:1397:7)
    at _combinedTickCallback (internal/process/next_tick.js:77:11)
    at process._tickCallback (internal/process/next_tick.js:98:9)

Might be nice to capture this error and just say:

Cannot start a build server because you already have one running.

Include license in builds

Bug

Per https://github.com/dojo/meta/blob/master/LICENSE#L10-L17 , users of Dojo should include a copy of the license in their usage of Dojo. Our current build does not do this.

Expected behavior:

The following comment should be included in all built code:

/*
[Dojo](https://dojo.io/) 
Copyright [JS Foundation](https://js.foundation/) & contributors
[New BSD license](https://github.com/dojo/meta/blob/master/LICENSE)
All rights reserved
*/

Actual behavior:

Currently no copyright or license information is included in any built code

Should add module using `load` to the `CoreLoadPlugin` map when imported in tests

Bug

Currently if we build (with no auto bundling) a project that uses load(require, './MyWidget') and the module is imported in unit tests, the tests fail for Missing module: src/MyWidget.

Expected behaviour is to ensure that modules are added to the map in CoreLoadPlugin if they are imported in the unit tests even if the load is registered in the projects src directory.

Can't load CSS modules from node modules

Bug

It looks like you can't build code that imports CSS modules that aren't in the src/ directory. I think it's a problem with src/loaders/css-module-dts-loader/loader.ts#getCssImport.

This was discovered while looking into dojo/meta#138 .

Code

import * as localStyles from './some/local/file.m.css';
import * as foreignStyles from '@dojo/widgets/common/styles/base.m.css';

You can error when running dojo build.

Expected behavior:

I expect it to build ๐Ÿ˜„

Actual behavior:

(node:28421) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: ENOENT: no such file or directory, stat '/Users/rorymulligan/Desktop/dojo2/examples/todo-mvc/src/@dojo/widgets/common/base.m.css

Build fails on Windows

Bug

The build currently fails on Windows. The TypeScript loader doesn't appear to find targeted files, as no compilation takes place.

Code

$ dojo build
Hash: f11b80610fe96c355d9f
Version: webpack 1.13.3
Time: 5982ms
                           Asset       Size  Chunks             Chunk Names
                       main.styl    0 bytes          [emitted]
                     src/main.js    1.89 kB       0  [emitted]  src/main
                 src/main.js.map    1.88 kB       0  [emitted]  src/main
                    main.css.map   85 bytes       0  [emitted]  src/main
                      index.html  253 bytes          [emitted]
                        main.css   36 bytes       0  [emitted]  src/main
                 styles/app.styl   39 bytes          [emitted]
 styles/structural/_css/test.css   37 bytes          [emitted]
styles/structural/_css/test2.css   38 bytes          [emitted]
      styles/structural/test.css   28 bytes          [emitted]
     styles/structural/test2.css   29 bytes          [emitted]

ERROR in src/main.js from UglifyJs
SyntaxError: Unexpected token: name (css) [./src/main.ts:2,0]
Child html-webpack-plugin for "index.html":
         Asset    Size  Chunks       Chunk Names
    index.html  1.6 kB       0
Child extract-text-webpack-plugin:

Expected behavior:

The build should log information about ts-loader and tsconfig.json and actually compile TypeScript.

Actual behavior:

No typescript compilation occurs.

Stylus support

Enhancement

We should support CSS modules written in Stylus.

Include linting with tslint on build and watch

Enhancement

Having started a Dojo 2 project, it would be very helpful if the build included running tslint on build and watch.

We could include the tslint-loader based on whether project has a tslint.json included.

Perhaps something like:

	let tslintExists = false;
	try {
		require(path.join(basePath, 'tslint'));
		 tslintExists = true;
	} catch(err) {
		// do nothing
	}
...includeWhen(tslintExists, () => {
	return [
		{
			test: /\.ts$/,
			enforce: 'pre',
			loader: 'tslint-loader',
			options: {
				tsConfigFile: path.join(basePath, 'tslint.json')
			}
		}
	];
}),

Enhance `build` to produce layer files

@rishson commented on Mon Oct 03 2016

A lรก dojo1.


@kitsonk commented on Mon Oct 03 2016

Refs dojo/meta#34


@matt-gadd commented on Fri Oct 14 2016

@rishson can we state the problem rather than dictating a solution. there are a variety of ways we will want to make our apps performant at build time.


@rishson commented on Fri Oct 14 2016

@matt-gadd fair point. I'll create a 'performance' epic on cli to start discussion on what we can do to create well behaved, performant apps.


@kitsonk commented on Fri Oct 14 2016

So are we keeping this open then?

As far as a user story, I would say this one is one like this:

In complex web applications with multiple views, where certain views were in order to have a functional application, not all modules are needed to be loaded upon page load, and groups of modules, with any additional dependencies not already loaded, can be loaded efficiently.

In Dojo 1, this was accomplished by allowing the developer to group modules into logical sets which then allowed the developer to specify "layers" to allow efficient incremental loading of code and other resources as triggered by certain actions in the application.


@agubler commented on Fri Oct 14 2016

I think that this would certainly warrant being kept open as a story, maybe under the wider performance epic.


@agubler commented on Wed Feb 01 2017

This should probably be moved to cli build, but with more details of the problem

Add manual file bundling

Enhancement

Given a .dojorc like this:

{
    'build': {
        'bundles': {
             'foo-bundle': [
                 './src/todo/Foo',
                 './src/something/Else'
             ]
        }
    }
}

Create a bundle foo-bundle consisting of the given files.

Generate css-module d.ts files as part of build command.

css-module-typings should be created as part of our webpack build process. Furthermore they should be included in the watch process such that they are generated as they are edited.
An attempt was made to use typed-css-module-loader but this was not sufficient. There are outstanding PR's and issues on this loader which may provide a solution but it's likely that we may need to create a typescript pre-loader which plucks out the .css imports and creates the appropriate typings.

Improve the README with the build details

We should expand the README with:

  • what the build does
    • what gets built and where
    • why this is beneficial (size etc)
    • what is part of the build (sourcemaps, js rather than ts, css and why it looks weird)
    • what our widgets look like once built (what they contain etc)
  • how the build does it (uses webpack, but light on details)
  • cover the various scenarios, build for dev, build for prod..

Add bundle size reporting to build

Enhancement

We should add reporting to the build so people can profile the bundles they are generating. This should only be ran on a prod dojo build (not dev mode with -w). There are 2 good plugins for webpack out there:

https://github.com/th0r/webpack-bundle-analyzer - creates a tree map and supports both post minification and gzipped analysis of bundles. One issue might be that I think the visualization it creates is provided by a library which is commercial - so might want to check that.

https://github.com/chrisbateman/webpack-visualizer - generates a pretty sunburst visualization, but as far as i'm aware only shows sizes pre minification.

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.