As someone who has tried to find a way to help content authors develop and maintain big web sites by creating (HTML) components for years, I\'m really excited to see web compone
We just try and keep our web component javascript to a bare minimal, keeping their footprint down very low. So instead of using underscore for whatever, we'd just use the native ES6 equivalents (considering the existing use web components, this isn't much of a stretch).
We then package our web components with one html file, one css file, and one js file. They can actually be made up of multiple files, but our build process takes care of that. Our javascript file is bundled with Browserify, allowing us to use npm modules, while have them nicely packaged within our web app.
This offers really nice tiny, but blackbloxed web components, that can share common modules without any conflicts, and without having to worry about AMD overhead, just simple commonjs for everything.
If we ever do need to bundle a heavy library across multiple components, we would either make that library external and pass it in, leaving the inclusion up the application (this is how you have to do it with backbone.js, due to backbone.js using instanceof instead of duck typing, making multiple backbone.js instances talking to each other impossible), or have the web components bundle it in using a browserify cdn server like wzrd.in — however, much better for the parent web app to handle large deps, as if the web components use different cdns, then you have a issue.
Say that I develop component A which has a dependency for underscore.js and want to use components B and C which have dependencies on lodash.js version 1.*, etc. I don't see any way to flag dependencies and library versions.
There's an old ECMA spec from 1999 (ECMA-290) that specified a component mechanism which included elements and attributes for dependencies and library versions:
<component
name="com.mycompany.selectnav"
displayname="SelectNav"
src="selectnav.js"
env="client"
hint="Navigational Select List"
version="1.0"
needsform="yes">
</component>
For dependencies, use the customizer
element. For versioning, use the meta
element. For example:
<customizer type="ecmascript" url="http://com.com/foo">
<meta name="version" value="1.1b"/>
</customizer>
A JSON encoding for modern implementation would look like:
{
"component":
{
"name":"com.mycompany.selectnav",
"displayname":"SelectNav",
"src":"selectnav.js",
"env":"client",
"hint":"Navigational Select List",
"version":"1.0",
"needsform":"yes",
"customizer":
{
"type":"ecmascript",
"url":"http://com.com/foo",
"meta":
{
"name":"version",
"value":"1.1b"
}
}
}
}
Lifecycle callbacks integrated with a CDN API, an API checker, and an on-demand script loader would be another option:
createdCallback => check API URL => createElement for dependent script tags => onload event for dependent script tags => appendChild for dependent script tags
Subsetting HTML as in the following projects is a solution which has been tried numerous times:
GitHub - ampproject/amphtml: AMP HTML source code, samples, and documentation. See below for more info.
XHTML™ Basic 1.1 - Second Edition
X-Tag ★ Web Components
coverage-ext
How To Clean Up Your JavaScript Build With Tree Shaking
Eliminating Unused CSS
Analysing and minimising the size of client side bundle with webpack and source-map-explorer
polyfill.io
References
ECMA-290: ECMAScript Components Specification (PDF)
Browser-based distributed evolutionary computation: performance and scaling behavior (ACM)
Custom Elements Callback Queue
Web Components Custom Elements Specification: Types of Custom Elements
Lazy evaluation of CommonJS modules
The Cost of Small Modules
Yepnope load from CDN with Fallback (Example)
Providing Local JS and CSS Resources for CDN Fallbacks · Edd Mann
Plugin Pros and Cons
Caja Playground