Skip to content
This repository has been archived by the owner on Feb 7, 2019. It is now read-only.

Investigate generating self-contained brick.js + brick.css #193

Open
sole opened this issue Jul 10, 2014 · 17 comments
Open

Investigate generating self-contained brick.js + brick.css #193

sole opened this issue Jul 10, 2014 · 17 comments

Comments

@sole
Copy link
Contributor

sole commented Jul 10, 2014

And possibly a version with platform.js and another one without it.

Why? Because I don't want to ship Mortar templates with a dependency that loads a gazillion files on demand. Also because including a .js file + a .css file in a site is so much easier, and we'd hopefully won't be forcing devs to fire up a local server only to check out the template because otherwise weird errors happen (see #192 for reference), and people new to HTML and the web are like wut?

@sole sole added the confusing label Jul 10, 2014
@potch
Copy link
Member

potch commented Jul 15, 2014

I intend to offer a 'brick.min' html import that only has one js and one css file, respectively. There is a possibility of converting all the templates to JS and offering a pure JS+CSS, but that would not be something people could easily do a la carte. Documenting and teaching people about best practices re vulcanize and bower is good, but won't help the mortar use case.

@sole
Copy link
Contributor Author

sole commented Jul 16, 2014

In Bugzilla: https://bugzilla.mozilla.org/show_bug.cgi?id=1039467 - please close when done? :-)

@sole
Copy link
Contributor Author

sole commented Aug 6, 2014

I did a preliminary exploration with vulcanise but I can't get too far away. I checked all and ran all the bowers and npm installs and stuff, then npm install vulcanize and changed to the dist folder to run this

../node_modules/.bin/vulcanize -o bundle.html brick.html

But...

fs.js:432
  return binding.open(pathModule._makeLong(path), stringToFlags(flags), mode);
                 ^
Error: ENOENT, no such file or directory '/Users/sole/data/brick/dist/brick-common/brick-common.html'
    at Object.fs.openSync (fs.js:432:18)
    at Object.fs.readFileSync (fs.js:289:15)
    at readFile (/Users/sole/data/brick/node_modules/vulcanize/lib/vulcan.js:54:20)
    at readDocument (/Users/sole/data/brick/node_modules/vulcanize/lib/vulcan.js:93:23)
    at concat (/Users/sole/data/brick/node_modules/vulcanize/lib/vulcan.js:99:13)
    at Object.<anonymous> (/Users/sole/data/brick/node_modules/vulcanize/lib/vulcan.js:117:27)
    at exports.each (/Users/sole/data/brick/node_modules/vulcanize/node_modules/cheerio/lib/api/traversing.js:268:24)
    at processImports (/Users/sole/data/brick/node_modules/vulcanize/lib/vulcan.js:113:24)
    at concat (/Users/sole/data/brick/node_modules/vulcanize/lib/vulcan.js:102:5)
    at Object.<anonymous> (/Users/sole/data/brick/node_modules/vulcanize/lib/vulcan.js:117:27)

and brick-common/brick-common.html is definitely not in the dist folder. So I don't know...

@sole
Copy link
Contributor Author

sole commented Aug 6, 2014

OK I found something! Seems like vulcanize is not happy with html imports relative paths including ../. I tried this with another component I'm playing with and it didn't work because I was including a component using ../ in the path.

If I copy the component inside the folder (for example as you could do if the dependency was managed with bower_components/something) and the html import is not using that lethal string, I can get vulcanize to run.

@potch
Copy link
Member

potch commented Aug 6, 2014

Hmm, we are using vulcanize with ../ paths in a bunch of places, and it doesn't seem to be exploding. Can I see an example of the code somewhere?

@sole
Copy link
Contributor Author

sole commented Aug 6, 2014

@potch I'm building an example to try to reproduce it with the minimum code!

@sole
Copy link
Contributor Author

sole commented Aug 8, 2014

So for anyone who stumbles upon this, the issues were due to some misconfiguration of Brick generating a dist folder with some missing files, and so Vulcanize was "going bananas". Once this is fixed Vulcanize can do its thing, but the output is not a JS + CSS but an HTML (import) + CSS.

@fwenzel
Copy link

fwenzel commented Aug 19, 2014

What's the status of HTMLImports in the platform? If they work, then this works as well as one JS, one CSS file, right? If not, then let's figure out what we can do to digest this down to JS/CSS from HTMLImports, for distribution only.

Vulcanize's readme says, --inline --csp does "Bundle all javascript (inline and external) into outputfilename.js". That might be what we need?

@sole
Copy link
Contributor Author

sole commented Aug 20, 2014

Vulcanize generates a js file AND an html file, and that is what the build script is generating right now (see here). The way Brick 2 works, templates are defined and css styles are included using html imports (which are "concatenated" into the html file). This is so styles are scoped and using shadow dom and stuff.

Last time I spoke to Potch he was going to look into "processing" the generated html file because it wasn't entirely correct (there were mismatched closing </html> tags and things like that).

This sort-of-works but

This could be fine in the future when there's support for all of this in Gecko's platform, but that future might be months, or years away. I'm not familiar with the speed of implementing a new API which has a moving spec in Gecko, so I can't foresee how many months/years this is.

@lmorchard
Copy link

Vulcanize's readme says, --inline --csp does "Bundle all javascript (inline and external) into outputfilename.js". That might be what we need?

Poking at this issue a little. Unfortunately, --inline --csp does not produce a single outputfilename.js that's just JavaScript. Like sole said, it produces both an HTML file and a JS file.

Might take a look through how the platform polyfills work, but not sure any of Brick 2 can work without some form of HTML Imports. Maybe we can do something funky that embeds the HTML as strings in JS and somehow hot-wires the HTML import polyfill that way? That seems like a nasty hack though.

@fwenzel
Copy link

fwenzel commented Aug 25, 2014

That also seems like it'll violate CSP, won't it?

@sole
Copy link
Contributor Author

sole commented Aug 26, 2014

We could generate that JS that has the strings for the templates, and unless I'm overlooking something, I don't think that it would create CSP issues, since we're just creating nodes (HTMLTemplates) and assigning their contents on the fly, but not running eval. Templates are inert HTML until instantiated.

@fwenzel
Copy link

fwenzel commented Aug 26, 2014

Good points, sole, thanks

@lmorchard
Copy link

Okay, so I tried an experiment and I'm trying to decide how bad an idea it is.

Here are some relevant links:

Rather than vulcanize, I wrote a quick & dirty gulp task to embed HTML in JS for an all-in-one component library. There's also a small hack in the component to use the embedded HTML when available, or to use document.currentScript.ownerDocument otherwise.

Basically, this is just a hack around avoiding the use of an HTML Import.

@sole
Copy link
Contributor Author

sole commented Aug 27, 2014

Ohhh coolness! So it's as I was imagining: to implement this in the existing (new) Brick components we'd have to add this sort of "shim" to each component + build script (?).

I'm torn as to whether it's worth doing it:

a) on one hand it makes the components way easier to distribute because it is just a JS file! Wow yay!
b) on another hand it is not ... standard component behaviour or form, and we have learnt that straying from the "worn out path" tends not to work too well when there are huge players in the game already. Unless your game turns out to be quick, and dare I say it, deadly in its execution--which makes it dead obvious to stand by your side and not by the huge player.

Also, edge cases--have you given it a thought about how it could work with recursive html imports? I think this is something vulcanise covers. Your tool should maybe start parsing the html and seeing if there are more imports, and including them into the __DATA string.

For example, I wrote a component that used html imports for including another component but this included component was also including stuff using another html import line. If I ran your script over my component I would end up with the first level of imports but not the second so it wouldn't be possible to run it correctly.

@lmorchard
Copy link

So far, I just wanted to see how cumbersome it would be to cram a single HTML "import" into the JS. So, I hadn't really gotten into the full use cases of vulcanize yet

And yeah, we'd need to shim every brick component and tweak build scripts. That's not pretty. I'm trying to think through how that might be done more cleanly. Maybe I could hack the polyfills so that document.currentScript.ownerDocument just gets the right HTML without tweaks to the component JS.

But, if this HTML-in-JS thing is not a terrible idea... For recursive component includes, I could concat all the JS together. Then, I could wrap the whole mess with a table of HTML files used by all the JS like this:

(function (__FILES) {
...
}({
    'aio-play1.html': '<html>...',
    'component2.html': '<html>...'
})

Also, if this works, I can see whether this could be a patch to vulcanize itself. That could be handy if it got accepted upstream. But, that's getting way ahead of things :)

@lmorchard
Copy link

Spent some time yesterday and today sketching out a vulcanize-esque tool that crams everything into a single JS include. I called it "introvert", because it kind of turns vulcanize inside out.

Trying to figure out how to possibly make this just work with existing Brick components. But, as of right now it requires one small tweak to find the ownerDocument that's no longer available via HTML Imports.

I haven't actually tried this out in a browser yet, but the output result looks like this:

;(function () {
  function __loadHTML(html) {
    var doc = document.implementation.createHTMLDocument('import');
    var meta = doc.createElement('meta');
    meta.setAttribute('charset', 'utf-8');
    doc.head.appendChild(meta);
    doc.body.innerHTML = html;
    return doc;
  }

(function (_ownerDocument) {

(function () {
  // x-dep.js

  var importDoc;
  if (typeof _ownerDocument !== 'undefined') {
    importDoc = _ownerDocument;
  } else {
    var currentScript = document._currentScript || document.currentScript;
    importDoc = currentScript.ownerDocument;
  }

  var template = importDoc.querySelector('template');

  /* ... */
});

})(__loadHTML("<!-- x-dep.html -->\n<template>\n  <style>/* x-dep.css */\n</style>\n  <img src=\"http://www.polymer-project.org/images/logos/p-logo.svg\">\n</template>\n\n\n"));

(function (_ownerDocument) {

(function () {
  // x-app.js

  var importDoc;
  if (typeof _ownerDocument !== 'undefined') {
    importDoc = _ownerDocument;
  } else {
    var currentScript = document._currentScript || document.currentScript;
    importDoc = currentScript.ownerDocument;
  }

  var template = importDoc.querySelector('template');

  /* ... */
});

})(__loadHTML("<!-- x-app.html -->\n\n\n<template>\n  <style>/* x-app.css */\n</style>\n  <x-dep></x-dep>\n</template>\n\n\n"));

})()

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants