x)- [X] bug report -> please search issues before submitting
- [ ] feature request
@angular/cli: 1.0.0
node: 6.9.2
os: win32 x64
@angular/animations: 4.0.1
@angular/common: 4.0.1
@angular/compiler: 4.0.1
@angular/core: 4.0.1
@angular/forms: 4.0.1
@angular/http: 4.0.1
@angular/platform-browser: 4.0.1
@angular/platform-browser-dynamic: 4.0.1
@angular/router: 4.0.1
@angular/upgrade: 4.0.1
@angular/cli: 1.0.0
@angular/compiler-cli: 4.0.1
I need to provide different global styles for certain customers to my website and once they login, override certain bootstrap variables (colors, logo, etc). I have defined some client specific SCSS files and marked them as lazy load in the styles array.
Now I need to load them...help!
Docs in the link below mention "You can also rename the output and lazy load it by using the object format" - so how do I load them?
https://github.com/angular/angular-cli/blob/master/docs/documentation/stories/global-styles.md
When looking at the cli output, the lazy loaded files are generated, so with:
"styles": [
{"input": "../test-style.scss", "lazy": true, "output": "test-style"}
],
There will be a test-style.bundle.js generated:
chunk {4} test-style.bundle.js, test-style.bundle.js.map (test-style) 9.88 kB {7} [initial]
However I didn't really manage to find a civil way of importing that bundle withing the app code. The bundle can be imported in the index.html via script tag, but importing it before inline.bundle.js will result in webpack error. Importing it afterwards will work - this can be done from the app code by appending the script tag with the bundle output name:
function loadScript(scriptUrl) {
const script = document.createElement('script');
script.src = scriptUrl;
document.body.appendChild(script);
}
loadScript('test-style.bundle.js');
This will load the styles, but it is hardly an ideal solution. I as well would really like to know a proper way to load lazily both styles and scripts (as this is applicable to scripts as well). It should also be added to the docs I think.
Just tried this too. I Copy/Pasted styles.scss and called it lazy.scss then added it like in the story.
/styles.bundle.js // this is added eagerly/lazy.bundle.js // I can add this manually to index.html or load it programmaticallyIt would be great If someone describes .. how to programatically refer the lazy generated Script / Styles at runtime.. the bundles are generated at build time.. but couldn't find a proper way to load at it runtime.
@a5hik unfortunately the CLI doesn't support programmatically adding lazy scripts and styles because there isn't a way to tell when it should be loaded. You will have to do that yourself.
I actually ended up moving all the global scripts and styles to corresponding modules.. wanted to load everything lazily..
Closing as above.
I don't know why this was closed. The question still very much remains.
When I lazy load a css file, the production build process output includes a chuck hash that I can't know, making it impossible to know in my code the name of the file. Let me show. If I add the following to my angular-cli.json:
"styles" : [
{ "input" : "foo.css", "lazy" : true }
]
then the build will output a file called foo.<some random hash>.bundle.js.
Because the file name is generated and not static, I can't lazy load it. How do I get either the name to be static... or what is the prescribed way to do this by the Angular CLI team? I have the ability to create the lazy css file. How do I use it?
@filipesilva ^^^
@filipesilva any idea about this?
Are there any specific documentation about how to properly use globally lazy loaded scripts?
https://github.com/angular/angular-cli/wiki/stories-global-scripts
docs written here is kinda vague that its hard to know how to properly use in the "real world"
@aaronfrost, use the option bundleName with your lazy loaded style:
"styles": [
{
"input": "lazy-style.scss",
"lazy": true,
"bundleName": "lazy-style"
}
],
Then angular compilation will generate a bundle named lazy-style.js. You can then lazy load it somewhere like this:
const element = document.createElement('script');
element.src = 'lazy-style.js';
document.body.appendChild(element);
@rafagsiqueira i did everything that you did, then run npm start , but i don't see my bundle.
{
"input":"../src/assets/workflowengine/js/workflowdesigner.min.js",
"lazy":true,
"output": "lazy-wfdesigner"
}
I see all others bundles loaded in index.html which is fine. Where to look for lazy bundle?
edit: i tried also with "bundleName" instead of "output", result is the same
This is what I use to create my lazy style bundle
{
"input": "src/styles/lazy-styles.scss",
"lazy": true,
"bundleName": "lazy-style"
}
This is how I load the bundle in my app.component.ts' constructor
// Add lazy loaded css
if (environment.production) {
const element = document.createElement('link');
element.rel = 'stylesheet';
/* Only works as stylesheet but not with preload
element.rel = 'preload';
element.as = 'style';
*/
element.href = 'lazy-style.css';
document.body.appendChild(element);
} else {
const element = document.createElement('script');
element.src = 'lazy-style.js';
document.body.appendChild(element);
}
Why is there a .js file in development mode and it compiles to a .css file in production? Is there any reason for this or did I just configure it the wrong way?
@madmurl0c the JS file in dev builds is for faster CSS rebuild. You can make it always be css with --extractCss=true. If you set this on the build options in angular.json, it will always apply.
@filipesilva Thanks, extractCss did the trick :)
For anyone having issues with this, the following works fine for me:
angular.json
"styles": [
"src/styles/styles.scss",
{
"input": "src/styles/lazy-styles.scss",
"lazy": true,
"bundleName": "lazy-style"
}
],
"extractCss": true,
constructor in app.component.ts
const preloadElement = document.createElement('link');
preloadElement.rel = 'preload';
preloadElement.as = 'style';
preloadElement.href = 'lazy-style.css';
document.body.appendChild(preloadElement);
const lazyStyleElement = document.createElement('link');
lazyStyleElement.rel = 'stylesheet';
lazyStyleElement.href = 'lazy-style.css';
document.body.appendChild(lazyStyleElement);
Hi,
What's bothering me here with this approach, is that we do access DOM directly and not using abstraction. What should be the prefered way to do so ?
One other question: let's say i change my angular.json file to add { "input" : "myUrl", "lazy": true, "bundleName": "myBundle"} in the Builder configuration. This applies only for ng build , right ?
But what if i want those exact same file in my dev process, by doing ng serve ? For the dev process, it seems to me that I can't have a way to lazy load those same files.
Or am i missing something ?
Maybe I should open another issue ? I couldn't find any relevant information about this on the web & docs.
@johanchouquet neither Angular or Angular CLI provide an abstraction for lazy loading CSS. Angular CLI just creates CSS bundles that aren't automatically loaded. I don't think that Angular itself needs to provide an abstraction for it either, mostly because it's not Angular specific.
Since ng serve actually uses the build configuration, both will have the lazy CSS bundle.
@johanchouquet neither Angular or Angular CLI provide an abstraction for lazy loading CSS. Angular CLI just creates CSS bundles that aren't automatically loaded. I don't think that Angular itself needs to provide an abstraction for it either, mostly because it's not Angular specific.
Since
ng serveactually uses thebuildconfiguration, both will have the lazy CSS bundle.
Thanks @filipesilva . That's clear for me for ng serve and ng build 馃憤 !
About the abstraction in Angular, I understand that the CLI provides the starting solution and this part of the job is done i believe. But I'm more interested in the 'How to use the JS scripts that have been lazy loaded' part ?
Because, to me, this solution would work only in a browser environment, right ? So what about server side, or in web worker etc ... ? Shouldn't we take car of this using for example Renderer2 at the very least ? But even doing so, we still would have to interact with the nativeElement and call some method to create the nodes. And that's what i think is discouraged by the Angular team.
Again, this may not be the best place to talk about it, but sure where it'd be better. Sorry for that.
Personally I haven't given much thought about how to use lazy loaded js/css in a server environment. But the default builder in Angular CLI is only mean to build browser apps, so I don't think that's something that should be covered there. The folks at https://github.com/angular/universal, who cover the server journey, would know more.
@filipesilva, this is true indeed. So, maybe this is not a big deal. I was just wondering about code portability there. So this makes sense to do inject those scripts in the DOM directly.
This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.
Read more about our automatic conversation locking policy.
_This action has been performed automatically by a bot._
Most helpful comment
I don't know why this was closed. The question still very much remains.
When I lazy load a css file, the production build process output includes a chuck hash that I can't know, making it impossible to know in my code the name of the file. Let me show. If I add the following to my
angular-cli.json:then the build will output a file called
foo.<some random hash>.bundle.js.Because the file name is generated and not static, I can't lazy load it. How do I get either the name to be static... or what is the prescribed way to do this by the Angular CLI team? I have the ability to create the lazy css file. How do I use it?
@filipesilva ^^^