Comments (88)
From an API point of view, I vote option 1, or option 2 as <require from="./hello.html" />
. I agree the option 3 will lead to a very crowded and hard to read line.
from aurelia.
I don't think that reintroducing <require>
with limitations or known issues is a good move.
I think it should be all or none.
from aurelia.
I think we should keep this the same as vCurrent. Any real objections to that?
from aurelia.
If we keep any declarative form of dependencies declaration in the view, that supports css, we need to resolve the css order issue.
I can't find the original issue, so in short: the <require>
syntax mirrors the ES import
, so order is irrelevant, but when it comes to importing css order matters.
I suppose we can either approach this by syntax or by "executing" the imports sequentially.
Examples(do not view as proposition):
<require from="vendors/bootstrap.css">
<require from="./app.css"></require>
</require>
I understand the above makes the parsing somewhat more complex, but we need to resolve this in one way or another.
from aurelia.
Whatever syntax we choose should work in JIT mode. I really don't want to require a full HTML parser to be embedded inside the JIT.
As long as we choose a syntax that is compatible with the HTML spec (e.g. the browser can parse it) then we don't need to. The AOT's parser and the browser's parser would work the same way. The AOT's parser would just be more efficient and produce a better performing runtime
from aurelia.
@Sayan751 Yep. I believe @EisenbergEffect is only testing locally with a WIP require plugin
from aurelia.
@Sayan751 The vNext runtime and compiler themselves don't contain any notion of how dependencies for a template are loaded, only that when the template is compiled or executed, the dependencies should be present. As we move forward, things like require
will most likely be handled inside the AOT system or loader plugins for those who don't want to use AOT or can't.
A few weeks ago I started experimenting with writing a vNext app. As part of doing that, I built a require.js plugin for JIT-mode development that handles require
/import
elements, HTML-only elements, and CSS imports. I shared a bit about my personal experiment in this RFC: #375
@fkleuver I was planning to fix up the current plugin-requirejs
package based on what I had built for my own app. It needs some refactoring to make it more generic, but I could create a branch and start working on that this week. It would enable some of our earlier adopters/experiments to work with vNext in a way that's more ergonomic in advance of AOT. What do you think?
from aurelia.
I’m strongly in favor of the <import>
outside the <template>
, so yes, that’s the proposal I’d vote for, @EisenbergEffect .
The <link>
element is tempting, but I’m leaning towards not mixing those things up. The thing is, it would not be a normal link, so if we used that, then we would:
-
violate the spec, as it clearly states that a
<link>
element must have arel
attribute. -
have to explain how and why our
<link>
is different from the spec - for example, ouras
attribute has a different meaning, there should be norel
, and all other attributes are invalid.
We would of course need documentation for this thing no matter what, but I think there will be less potential for confusion if we have our own thing, instead of a standard thing that behaves in a non-standard way.
The really fun example is this one:
What happens if we put a <link>
to a stylesheet in our template - should that have a rel
attribute, and if not, why not, given that the spec says it should? This could be confusing to new users.
Regarding naming, I definitely think import
is the best name. That’s what this concept is called in ES, so we should align with that, to keep things consistent - require
sounds way too much like a legacy or node.js thing to me.
from aurelia.
My current require.js plugin handles both require
and import
. It doesn't distinguish between inside or outside of the template at the moment. It's just a prototype though.
I don't see any issue in supporting what @thomas-darling suggests. We can effectively remove require
by not documenting it anywhere except in the migration docs as a backwards compat feature which will officially removed at some future release TBD. Newcomers don't even need to know that option exists.
from aurelia.
Hm didn't we discuss this somewhere else already? I honestly see zero issues with having both. It's 3 extra lines:
function preparseTemplate(html) {
const imports = [];
const len = html.length;
let i = 0;
let start = 0;
let ch = 0;
while (i < len) {
if (html.charCodeAt(i) === 0x3C) {
ch = html.charCodeAt(i + 1);
if (ch === 0x72 && html.charCodeAt(i + 2) === 0x65 && html.slice(i + 3, i + 8) === 'quire') {
start = i = i + 17;
while (html.charCodeAt(i++) !== 0x22);
imports.push(html.slice(start, i));
} else if (ch === 0x69 && html.charCodeAt(i + 2) === 0x6D && html.charCodeAt(i + 3) === 0x70 && html.slice(i + 4, i + 7) === 'ort') {
start = i = i + 16;
while (html.charCodeAt(i++) !== 0x22);
imports.push(html.slice(start, i));
}
}
++i;
}
return imports;
}
It parses the the average template with a couple of imports/requires in less than 0.1ms and that's without any optimization attempt or restrictions on where they are placed (the entire html string is parsed). What's the harm?
from aurelia.
Let me give a quick explanation that describes what basically happens:
Let's say you have resources/index.ts
and it looks something like this:
export * from './elements/index';
export * from './attributes/index';
And in elements/index.ts
you have something like this:
export * from './hello-world';
export * from './goodbye-world';
And in hello-world.ts
you have something like this:
@customElement('hello-world')
export class HelloWorld {
...
}
Assume similar patterns for the other files that are imported.
Now, let's say that you put this into your my-app.html
view:
<import from="./resources/index"></import>
That's going to turn into something similar to this in code:
import resources from './resources/index';
import template from './my-app.html';
@customElement({
name: 'my-app',
template,
dependencies: [resources]
})
export class App {
}
The dependencies
array for the element will eventually get passed along to the DI container for the element, something like this:
const definition = {
name: 'my-app',
dependencies: [resources]
};
const container = createContainerForElementClass();
container.register(...definition.dependencies);
The register
method of the container checks to see whether its argument is a registry
or if any of its properties are a registry
. Because the dependency above is a module object itself, this means that it will have a property for every export. Since we used star exports aggregated up, it means that the final module object will have a property for every single export under the resources
folder. Any class that has a registration decorator (e.g. @singleton
or @transient
) functions as a registry. Every custom element, custom attribute and all other resource types are registries because their @customeElement
, etc. decorators effectively apply behaviors similar to @transient
.
The end result of this is that a single import
can bring in an entire collection of resources for use within a view. So, even if you don't want to use global resources, you can still have a way to import a standard set of resources with a single import
in your view.
Now, on to the proposal regarding these two being the same:
<import from="components/index"></import>
<import from="components"></import>
That's really up to the module loader and/or AOT process. This is the way it would work in node.js. I believe that system.js works this way and that require.js can be made to work this way as well. However, it is not the way that the WHATWG standard module loader operates at present. I believe some of the currently being discussed improvements to the standard loader, enabling configuration of paths, etc., would enable this in the future. However, it's not going to work automatically in any of the cases above, except Node, I believe.
from aurelia.
Actually, option three is kind of nice. Not sure if it would get crowded though. I'm pretty open on syntax as long as it's something we can extract inside of a loader plugin without needing to include an entire html parser to do it. The trick is that this data has to be extracted before the template is sent to the compiler and we want to avoid double parsing the html.
from aurelia.
auto-trace cli already has htmlparser2 installed to deal with <require>
tag.
aurelia-webpack-plugin also has access to webpack's html parser for same purpose.
The parsing part is not a problem. The extra parsing is in compile time, I don't think we have double parsing in runtime.
from aurelia.
I got your point now. I think you are talking about dynamic component loading at runtime (supported by jit app).
We can enforce only support require
attribute if it's the first attribute of template
tag. I think it's a good trade-off for both syntax and usability.
This also makes the "view!" plugin easier to remove the require
tag from cleanedTemplate.
from aurelia.
Probably option1 fits better with Aurelia's spirit of standard compliant.
In HTML5 browser native parser, <require from="./hello.html" />
is treated exactly same as <require from="./hello.html">
, result is same as missing closing pair. But I like the compactness.
from aurelia.
Can we eliminate that use case completely, and limit <require>
to Aurelia HTML behaviors?
from aurelia.
What about a variant of option 3?
<template
require="./h.html"
require="./h.css"
>
</template>
This is valid html. The order of attributes are not an issue on IE/Edge, as require
attributes will be extracted out by regex (or some nodejs html parser at bundling time) in view plugin, not by native browser html parser.
from aurelia.
Let's not worry about complexity of parsing. I'm going to build a html parser for the aot
module anyway, it will be spec compliant, and we should be able to add a few custom rules to it specific to Aurelia. During AOT we can parse the html to extract out any requires as well as have the template compiler process it in the same pass. There are ways to do that.
So whatever gives the nicest API is what we should go with.
from aurelia.
@fkleuver And that will work with the JIT also? Or we will have AOT only features?
I find it confusing having multiple definitions of the same attribute.
from aurelia.
Right now there's no notion of the require syntax anywhere in the core. The core expects a list of dependencies, and doesn't care where they come from. This syntax only exists inside the requirejs plugin, which extracts the paths and uses them to load the modules so that it passes the dependencies along to the compiler. This turns out to massively simplify many, many things.
Whatever syntax we choose should work in JIT mode. I really don't want to require a full HTML parser to be embedded inside the JIT.
from aurelia.
I really don't want to require a full HTML parser to be embedded inside the JIT.
Of course not. JIT is a runtime thing, we have the browser to parse HTML there. I'm talking strictly about AOT here. AOT is running in nodejs runtime so you need an HTML parser anyway.
For JS/TS parsing in AOT we have the excellent typescript library that is maintained by a company with a lot of resources and smart people, so that's always going to be a safe bet.
There is no such thing for HTML / CSS as a standalone nodejs library so I'd prefer to do that ourselves. It is comparatively simple enough (with a core syntax that hardly ever changes) that we can do that ourselves.
Having our own HTML parser for AOT also means we can inject custom element processing and the sorts directly in there, save on the number of passes we need to do, and perhaps even end up with simpler code in the end. Not to mention the build time performance would be much better (not that this is a huge concern, but for a large business app it's nice to have a 30 second AOT processing time instead of a 2 minute one)
from aurelia.
@fkleuver And that will work with the JIT also? Or we will have AOT only features?
AOT in itself is a feature that only exists in, well, AOT. I wouldn't call any particular syntax "AOT only feature" though. That would imply you can do stuff in AOT that you can't do with the JIT. But AOT has much more information about the whole project available than the runtime ever could, so it allows you to write cleaner code by having to declare fewer things explicitly because the AOT can figure it out and glue it together
from aurelia.
As possible relevant note, @anything
clashes with ASP.NET Razor syntax which uses @ to introduce its own directives. It can be escaped (if used in a Razor .cshtml the line would be @@import './hello.html';
), but it feels slightly cumbersome.
from aurelia.
Yeah I don't think we need to change it compared to vCurrent. It works fine doesn't it?
from aurelia.
I mostly agree - the current <require>
element is the nicest way to do this.
I don't think it matters much whether it is inside or outside the <template>
element, although I guess having it outside might actually feel slightly more natural. Either one is fine though.
Personally, I also wouldn't mind if it was renamed to <import>
, just to keep the naming consistent with ES6. I've caught myself writing that by mistake several times, and although it would be a breaking change, it would also be super easy to rename with a global search and replace :-)
from aurelia.
Funny enough, we originally called it import
in the very, very early days of Aurelia but then discovered there was an issue with IE. I think it was IE10 but can't remember if it was fixed in later versions. I do and have always liked import
better. We could enable it for vNext and still support require
at the same time. It's mostly going to be handled inside either a loader plugin or AOT where this is pretty trivial. (It's actually not baked in anywhere into the runtime.) @fkleuver What are your thoughts?
from aurelia.
I don't see any issues with having both. Probably negligible parsing overhead.
from aurelia.
@huochunpeng How hard would it be to include <import from="...">
in the current CLI's tracing? I'd like to enable my vNext require.js plugin to support this but would also need equivalent support in the CLI's bundler. Thoughts?
from aurelia.
Super easy. You can try to modify your local cli find-deps.js findHtmlDeps
.
from aurelia.
Excellent to hear. I'll modify it in my local copy and try it out.
from aurelia.
Ok, that was super easy :) I can send a PR to the CLI. Are there tests on this particular area that I should extend @huochunpeng ?
from aurelia.
@thomas-darling we have to move require/import elements out of template element, because vCurrent has a very painful and confusing limitation.
If you have a component
<template>
<require from="..."></require>
<td></td>
<template>
Then try to use it as a tr
<tr as-element="my-comp"></tr>
It is an error because HTML standard doesn’t allow any tag other than th/td inside a tr element! There is nothing aurelia can work around since aurelia uses native browser html parser.
Moving require/import out of template can avoid vNext to fight html standard.
from aurelia.
I don't actually understand the problem here. The <require>
elements should be removed from the template before it's compiled anyway. Also, if they are outside the template, then in a single file components setup, where would they go?
from aurelia.
It certainly doesn’t work in vCurrent, there was some github issue on require inside tr.
I don’t think it’s an issue for future single file component format. The root is html format anyway, it is easy for compiler.
<import from=""></import>
<template></template>
<script></script>
<style></style>
from aurelia.
My point is that the require should never exist inside the tr
. It should be removed long before the template is instantiated and pushed into the tr
. It sounds like there's a bug in vCurrent somewhere, not so much in the design of require/import.
from aurelia.
I see you were talking about import tag inside template in vNext. Yes, it would not be an issue since we strip them.
from aurelia.
They should be stripped in vCurrent as well, I thought. If not, we should fix that for sure.
from aurelia.
In vCurrent, the resource loading is delayed to runtime when it sees the require element in DOM. If I am not wrong.
from aurelia.
They should be getting removed here: https://github.com/aurelia/loader/blob/master/src/template-registry-entry.js#L82 This happens when the module loader loads a template, more or less.
from aurelia.
If that is before the html fragment is appended to DOM, I need to test why vCurrent has issue in tr. Unless @bigopon knew something already.
from aurelia.
It is before it's even associated with a particular custom element. So, I think there may be something else going on here.
from aurelia.
Ref aurelia/binding#409 (comment)
from aurelia.
Update: the <tr as-element
with require
tag thing seems working fine now with current vCurrent. Strange. Something must have changed. I will test on IE and Edge when I got a chance next week.
from aurelia.
Just a question to avoid (my) confusion. I am trying v0.3.0-dev.20190117
. But, neither the @import ''
nor the <require from=''>
syntaxes are working. Is this something, still to be implemented?
from aurelia.
@EisenbergEffect Sounds good!
from aurelia.
Update: the tr require thing works in IE and Edge too. Now I am not sure what happened before when I encountered that issue.
from aurelia.
@huochunpeng Try it with two requires instead of one. I'm wondering if it's something to do with the implementation looping and removing things from a live node list going wrong.
from aurelia.
@EisenbergEffect two requires are fine. I found how to reproduce the bug. It's a combination of require and repeat.
<template>
<require from="./hello"></require>
<td repeat.for="v of [1,2,3]"><hello></hello> ${v} ${item}</td>
</template>
It supposes to render 3 td, but only 1 appears.
- Remove the require tag, it renders ok.
- Move require tag to be inside td, it renders ok.
Might be a repeater bug.
Use this repo https://github.com/huochunpeng/au-require-debug
from aurelia.
This is due to how native parser parse the template I believe, when tr, td are not the only child, it removes other elements
from aurelia.
Thx! yes, I can reproduce the problem without aurelia.
var t = document.createElement('div');
t.innerHTML =`<template>
<require from="./hello"></require>
<td repeat.for="v of [1,2,3]"><hello></hello> \${v} \${item}</td>
</template>`;
console.log(t);
[Log] <div>
<template>
Template Content
<require from="./hello"></require>
<hello></hello>
" ${v} ${item}"
</template>
</div>
The td is gone. That happens with or without repeat.for.
@EisenbergEffect that's a valid point we must move require/import out of template element.
from aurelia.
Actually, if we are renaming this thing anyway, we could just add support for the new <import>
- which is then only allowed outside the <template>
.
Then we can leave the old <require>
support as-is, but deprecate it and remove it later, in a minor version release. That way, people will have some time to update their projects...
But then again, vNext is a major version anyway, so personally I'd be fine with just taking the hit now, and keep things clean in vNext. It’s just a suggestion in case we really wanted to avoid breaking this.
from aurelia.
vNext has extra immunity to the browser parser limitation. The template in vNext is preprocessed by a small parser (not native browser parser) to strip require/import elements. So you would not encounter the browser limitation in vNext even when you put require element inside template element.
from aurelia.
Looks like @import
is out.
<require>
can not be inside or outside of the template tag.
Is there any reason to add thew new <import>
syntax?
from aurelia.
So, is this the proposal?
<import from="./hello"></import>
<template>
<td repeat.for="v of [1,2,3]"><hello></hello> ${v} ${item}</td>
</template>
I also started to wonder...why not use the link tag?
<link href="./hello">
<template>
<td repeat.for="v of [1,2,3]"><hello></hello> ${v} ${item}</td>
</template>
Basically, let Aurelia handle any link
without a rel
. Not sure if this would work or if we should do it, but thought I'd toss it out here.
from aurelia.
or . Since both are non-standard I say we keep to our existing require.
<link rel="import" href="./hello" />
Is the currently proposed HTML standard. I'm not sure what <link href="./hello">
will do in all browser by default, but my guess is that it will try to fetch. I dunno if that's a good thing or an undesired side effect.
from aurelia.
I mostly agree, but
That’s what this concept is called in ES, so we should align with that, to keep things consistent
But this isn't EcmaScript, this is HTML.
In any case, and both seem best.
from aurelia.
@davismj I know what you mean - but at least there will be some consistency then - if we go with require
there will be no consistency anywhere, except with node.js, which is just confusing.
We aready have the standard import
in ES and the standard link
in HTML - I see no reason to introduce require
as a third name, when it behaves pretty much exactly like an import
in ES.
from aurelia.
We already have <require>
in current, which makes it the strongest option.
from aurelia.
That's why I was arguing earlier, that we should maybe keep require
as-is (i.e. use inside the template), but deprecate it, and introduce <import>
as the new way of doing it, outside the template.
Then we can remove require
in a future, minor release.
If we have to move this thing anyway, then there's minimal effort required to also rename it.
Aurelia still has a relatively small user base, but a huge potential - so we should design for the future, not for the past, and right now we have a good opportunity to rename this thing to something better.
We won't get that again anytime soon 🙂
from aurelia.
Then we can remove
require
in a future, minor release.
Would be a major release, though. Breaking changes and all.
Aurelia still has a relatively small user base, but a huge potential - so we should design for the future, not for the past, and right now we have a good opportunity to rename this thing to something better.
100%, but this is just a minor naming thing. And we don't want to make more work for our loyal developer base unless they get something out of it.
from aurelia.
This can be renamed in 30 sec though - just do a global search and replace in **/*.html
😉
<require (.*?)></require>
-> <import $1>
from aurelia.
I think we're good.
from aurelia.
So we have two custom elements, and a single file that exports them.
components/index.ts
export { OneCustomElement } from './one';
export { TwoCustomElement } from './two';
I propose that
<import src="components/index"></import>
and
<import src="components"></import>
should have the same effect as
<import src="components/one"></import>
<import src="components/two"></import>
from aurelia.
I am going to do some preprocess on html.
@EisenbergEffect the information you provided above seems different from vCurrent.
<import from="./foo"></import>
<template>
...
</template>
The deps become:
import foo from './foo';
@customElement({
name: 'my-app',
template, // with only <template>
dependencies: [foo]
})
...
But vCurrent convention says the import should be import { Foo } from './foo';
with dependencies: [Foo]
. Please clarify the behaviour in vnext. I knew vnext has no need for the convention assumption, because every resources inside ./foo
have explicit decorators.
If that is the case, if ./foo
defined custom element FooA
and FooB
, the single import <import from="./foo"></import>
will make both <foo-a>
and <foo-b>
available in the html template.
Update the import foo from './foo';
seems incorrect, because it only gets the default
export, it cannot see other exports.
from aurelia.
I think we should be looking at native html modules actually, and make sure it will be compatible with that.
from aurelia.
I had imagined that this:
<import from ‘./foo’></import>
would turn into this:
import * as foo from ‘./foo’;
So that this could be done:
customElement({
dependencies: [foo]
}
export class Bar {
}
All the dependencies get passed to the vNext DI container’s register
method, which can handle two specific scenarios:
- An object with a
register
method. (Or a module that exports a register function, since a module is just an object). - If no
register
function is found, the keys of the object are iterated to see if any of them have values with aregister
method.
In this way, any ES module can be passed directly to the container’s register
method and the user can choose to imperatively add dependencies via implementing register, or just export (or re-export) other things which have register
methods. Decorators like customElement
, customAttribute
, etc. generate a static register
method on the class, so that any module that exports these, which is passed to the container’s register
method, will get registered in the container according to the rules of that resource.
Hopefully this all makes sense…
from aurelia.
One crazy idea I hadn’t thought of could be to turn views into a dependencies as well. So, given an HTML file like this:
<import from=‘./foo’></import>
<div>
<foo></foo>
</div>
The compiler could turn that into this JS module:
export default view = new CompiledViewHere();
export * from ‘./foo’;
Assuming that CompiledView
implements a register
method, this entire module could be passed as dependencies. We would need to make a change so that the view was looked up using a special key from the DI container.
Just brainstorming…
from aurelia.
Hmm. This wouldn’t quite work for html only custom elements though, as importing those would result in the view for another element getting registered, so there would have to be something a bit different. One idea is to just generate a register method and then enable it to register things differently in different contexts. Again, not sure all the details there, just thinking out loud…
from aurelia.
Here’s another idea. Given this:
my-element.html
<import from=“./foo”></import>
<import from=“./bar.html></import>
<div>
<foo></foo>
<bar></bar>
</div>
We could turn that into this:
import * as foo from './foo';
import { getHTMLOnlyElement as getBar } from './bar.html';
const bar = getBar();
export const name = 'my-element';
export const template = 'html or compiled view here';
export const dependencies = [foo, bar];
export function getHTMLOnlyElement() {
return CustomElement.define({ template, dependencies });
}
And then the custom element would do this:
my-element.js
import * as myConfig from ‘./my-element.html’;
@customElement(myConfig)
export class MyElement {
}
No custom DI needed now. This should “just work”.
from aurelia.
One complication to this is that if someone imports something with an .html
extension, it could be an html only element, an html module with a named element export, or an html module with an html only element. So, we might need some sort of helper function to test the shape of the module and determine what the actual import is:
import * as foo from './foo';
import * as barModule from './bar.html';
const bar = getHTMLOnlyElementOrHTMLModuleExportFrom(barModule);
export const name = 'my-element';
export const template = 'html or compiled view here';
export const dependencies = [foo, bar];
export function getHTMLOnlyElement() {
return CustomElement.define({ template, dependencies });
}
from aurelia.
And I suppose that the AoT process wouldn’t really need that helper function in the end, as it would be able to evaluate the shape of the import at compile-time. But, as a first pass, we could use a helper like this if needed.
from aurelia.
This all looks doable and clean.
One thing I want to highlight, it's that the dependencies are handled by html module. This is very important to keep transpiling as close as possible to one-to-one operation for .js file (when you mutate html file, you don't have to update js file). The one-to-one is important for watch mode.
There is one small issue in watch mode I have been thinking. When user created a new foo.js, the foo.html is yet to be created, foo.js will get transpiling without decorator (because we don't know if it's an element or just plain js class). Then user creates foo.html, we have to somehow tell the watcher to update foo.js transpiling too.
If no register function is found, the keys of the object are iterated to see if any of them have values with a register method.
I am not clear, does this step need to be recursive?
Question: is the described .register()
behaviour implemented? If not, I can hardly test my work.
One idea I can think of to avoid the verbose helper func to check the shape of html module (our or native) , is to build the checker right into .register()
logic.
from aurelia.
The register
logic is part of the core DI. It’s been implemented for over a year :) We don’t want that to be recursive. The code I show above should work today, if generated during build.
from aurelia.
Understand, my question around recursion is for the usage of following.
some-entry.js
export * as foo from 'au2-foo-plugin';
export * as bar from 'au2-bar-plugin';
Then you can just call
export * as some from 'some-entry';
(...).register(some);
Without recursion, I guess some-entry can export a register func, then manually call .register(foo)
and .register(bar)
in the register func. Is my interpolation right?
Update, my bad, I guess this should work:
some-entry.js
export * from 'au2-foo-plugin';
export * from 'au2-bar-plugin';
from aurelia.
I also have some concern around this:
export * as foo from 'foo';
(...).register(foo);
By esm standard, foo
is a namespace which is NOT a JavaScript variable. The whole thing works now because in practice, foo
is a JavaScript variable in current world.
Should future world strictly follows the esm standard, then is it right to pass a namespace to a function as parameter?
from aurelia.
Good point about re-exporting. No, that won’t work. You would have to explicitly re-export each symbol or provide a register function that was exported. I’m afraid to make the register method generally recursive…maybe there’s some way to detect if something is a module object itself and if so, then and only then to iterate its properties.
Regarding the concern in the 2nd post, I wouldn’t be worried about that. foo
is a reference to the module object itself, which has a const property for every export. That should always work.
from aurelia.
Also to note export * from ‘au2-foo-plugin’
would enable the exports to be registered, but if you do export * as foo from 'au2-foo-plugin';
, that’s not going to work.
from aurelia.
@EisenbergEffect question: aurelia v1 has implementation to inject css to html head, does Aurelia 2 have the feature too? Or Aurelia 2 defers the task to bundler?
I am thinking about how to deal with <import from="bootstrap/dist/css/boostrap.css"></import>
.
from aurelia.
@EisenbergEffect I am thinking of change your proposal
from
export const name = 'my-element';
export const template = 'html or compiled view here';
export const dependencies = [foo, bar];
to just
export default 'html or compiled view here';
export const dependencies = [foo, bar];
So that when user do manually import template form './a.html'
, they can still get a string back, this is least surprising (match existing behaviour like webpack's html-loader).
Then the injected code in my-element.js will be like:
import template, {dependencies} from ‘./my-element.html’;
@customElement({
name: 'my-element',
template,
dependencies
})
export class MyElement {
}
from aurelia.
@3cp I like the idea of exporting the html as the default export. That is intuitive and expected based on current text-type plugins for various bundlers. However, I think we should also export it as the template
property and we should include name
(based on file name). This enables simple manual configuration for non-conventional scenarios. I’ll probably want to add other exports to this as well, based on some of the vNext work I’ve been doing with require.js. For example, the associateView
decorator that attaches a view to a class without making that class into a custom element, so that compose can render it. We can talk more about that later, but I think there are a few different scenarios for importing the html that we want to cover in whatever we generate, making sure that we generate the same shape across all bundlers/loaders.
from aurelia.
Ok, so export the same string to both default
and template
?
from aurelia.
Yes. That will allow both usage patterns to work nicely.
from aurelia.
One complication to this is that if someone imports something with an
.html
extension, it could be an html only element, an html module with a named element export, or an html module with an html only element. So, we might need some sort of helper function to test the shape of the module and determine what the actual import is:import * as foo from './foo'; import * as barModule from './bar.html'; const bar = getHTMLOnlyElementOrHTMLModuleExportFrom(barModule); export const name = 'my-element'; export const template = 'html or compiled view here'; export const dependencies = [foo, bar]; export function getHTMLOnlyElement() { return CustomElement.define({ template, dependencies }); }
@EisenbergEffect I guess the getHTMLOnlyElement needs to add name
export function getHTMLOnlyElement() {
return CustomElement.define({ name, template, dependencies });
}
from aurelia.
I guess we would need to avoid duplicate instances for html only element?
let _htmlOnlyElement;
export function getHTMLOnlyElement() {
if (!_htmlOnlyElement) {
_htmlOnlyElement = CustomElement.define({ name, template, dependencies });
}
return _htmlOnlyElement;
}
from aurelia.
@EisenbergEffect I will leave out native html module for now, because the complication of whether to support <import>
tag at runtime which is probably needed for native html module.
from aurelia.
Yes, good points about the need for the name and caching of the defined element. We can delay the native HTMl module support for now too. That's mostly part of our single file component story. You would only use those if the HTML file contained both the template and JS code, for example.
from aurelia.
@3cp Should we close this as implemented now?
from aurelia.
Yes, implemented.
from aurelia.
Related Issues (20)
- Incorrect injection of parent custom element HOT 6
- New instance injected when using CustomElementDefinition#dependencies HOT 1
- OPEN COLLECTIVE FUNDS HOT 2
- [feature request] state plugin should be able to connect to redux devtools HOT 1
- 🏁 Roadmap & Iteration plan Q1 2024 HOT 3
- flickering caused by aurelia rendering content before clearing the old HOT 2
- [RFC] Custom element bindables take priority over custom attribute
- [refactor] remove define life cycle HOT 1
- Vite plugin for aurelia 1.x? HOT 4
- Router load attribute: broken when using id & parameters.bind HOT 7
- Injecting IHttpClient error after beta 11 update
- Router swallows DI errors HOT 7
- Restrict behavior of custom attribute single value binding and primary bindable HOT 8
- Tweak aurelia package reexports HOT 9
- Validation Package - Email validation HOT 7
- Replacing view factory containers
- Vite load issue. HOT 2
- Define `ts-jest` config under `globals` is deprecated HOT 2
- 2.0.0-beta.15 - using @inject is throwing errors HOT 3
- CSS modules support for Vite HOT 6
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from aurelia.