Unload modules/styles dynamically in webpack - reactjs

I have to import certain list of styles dynamically based on landing page and all the other pages.
but when navigating from landing page to another page, I have to unload bootstrap style, as bootstrap conflict with myStyle:
// if we are in landing page then load bootstrap otherwise load myStyle
if (props.location.pathname === '/') {
import(`./assets/css/bootstrap.css`);
} else {
import(`./assets/css/myStyle.css`);
}
this is what I have tried so far but it doesn't do anything.(my theme collapse because of conflicting styles)
what I want is a way to dynamically unload a style completely in a page.
if (props.location.pathname === '/') {
delete require.cache[require.resolve('./assets/css/myStyle.css')];
import(`./assets/css/bootstrap.css`);
} else {
delete require.cache[require.resolve('./assets/css/bootstrap.css')];
import(`./assets/css/myStyle.css`);
}
does Webpack support such a scenario?

Please let me take you a step back just to clarify what webpack is all about. It creates bundles according to defined entrypoints. Using import/require declarations it collects all the files that are necessary to create such bundles (using appropriate loaders).
Now, let me go back to your question. You are saying that under some conditions depending on URL address you need or need not bootstrap.
Assuming that you are not using SPA, you can load bootstrap in <script> tag independently on the page that you need (landing) and on others - don't. Assuming that you are creating SPA - I don't even know how to accomplish what you are looking for. Please remember that at the end of a day, after all what webpack does, we are given static html + css + js files.
Moreover, I don't quite get how the unloading would even look like, I feel that you may think about webpack-dev-server and HMR stuff which obviously should not be used on production.

Related

ReactJS Redux Loading Image Dynamically from Variable

I am currently working on a React + Redux Project and wanted to use language messages to render an image.
The problem is that, because the image name is dynamic (because of the language switching), I can't use require(imageVar) to load the image.
What I currently am working with is this (this is inside of the render() function):
FormattedMessage {...messages.fullLogo}>
{
(fullLogo) => <Img src={require(`${fullLogo}`)} alt="Banner" />
}
</FormattedMessage>
This should theoretically load the image from the url (yes fullLogo is a full url to the image).
What I tried inside of src={} was:
require(`${fullLogo}`)
require(fullLogo)
require("" + fullLogo)
require(String(fullLogo))
require(fullLogo.toString())
Everytime I try one of these (except the 3rd one - gives me an fatal error) I get an "Could not Load Module './img/image.png'" error.
I guess this means, that the name does load but require somehow cannot access the variable.
However if i put the path directly into the require() function. It successfully loads the image.
I don't want this though. I want it to load it dynamically.
Maybe you guys have some experience with it.
Thanks in advance!
PS: If you need any extra code, let me know!
You can't dynamically require files by variable at runtime, since require happens before runtime, when you bundle your app together (e.g. using webpack).
Based on how the packager works, this isn't really possible with require.
Packaging happens once before runtime so those variables don't have values yet.
What do you mean by langage switching ? What does message.fullLogo contains ? If it contains an url, just use that url without require:

dealing with systemjs load time and sequence - there must be a better way

I have a situation using system.js with an angular application where I need to be able to include specific System.import(f) statements on a per-page basis, but it was imperative that they all be included before angular finishes bootstrapping and loading up its module.
I spent a long time on this problem and eventually this is the workaround I devised;
in my config.js, I am doing this...
config.js
// .... configuration ... //
Promise.all([
System.import('jquery'),
System.import('angular'),
System.import('angular.ng'),
System.import('bootstrap')
]).then(function() {
$(document).on('angular', function() {
angular.bootstrap(document, ['module-name']); $('body').removeClass('cloak');
});
});
Then I have a css class named .cloak. I tried ng-cloak but found it wasn't doing the job (I suspect because I'm deferring the angular bootstrapping)
.cloak { visibility: hidden; }
then on my individual page, I use this sort of code to shoe-horn my page-specific imports and finalize the process.
<!-- Load SystemJS -->
<script src="assets/js/system.js"></script>
<script src="config.js"></script>
<script>
System.import('app/main').then(function (e) {
Promise.all([
System.import('app/controllers/index'),
System.import('app/controllers/read'),
System.import('app/controllers/edit/article'),
System.import('scripts/lib/init')
]).then(function (m) {
$(document).trigger('angular');
});
});
</script>
So that's the basic idea; I don't allow angular to finish wiring up its module until everything has been imported through system.js. At present, this seems to work fine.
My problem is that I'm not a very good programmer, nor am I very clever. This seems like an extremely standard, normal problem that comes with the way system.js is designed and it occurs to me that there has to be a better, built in solution that I'm missing or haven't found.
Has anyone else dealt with this before that can offer some advice?
The reason I need to defer the module wiring is because I've got various angular controllers and models and such and I don't want them all to load on every page. (I mean, trimming down the scripts to only the ones needed at the moment is one of the points of a module loader, aside dependency resolution).
Trying to use the ng-app directive was constantly causing trouble - as angular would try to load before everything was finished and loaded in, so it had trouble finding things like certain controllers and the like on certain pages.
The biggest reason I need an alternative is that this method doesn't work well for minifying typescript.
This is an extremely standard issue with ng-cloak in general. Perhaps a better way has come around, but pretty much since I started working with angular I've just defined ng-cloak in the header of my index.html file like this:
<style>
[ng\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak {
display: none !important;
}
</style>
and added class="ng-cloak" to the body tag of my page. It works great and when Angular finishes loading it's internal ng-cloak styles effectively overwrite mine.
It seems like moving the inline script basically as is, to an external file, would still allow it to run exactly as you have it and then minification and such would be fine.
It also sounds like you're not creating a SPA here, since if I understand you correctly, you're calling config.jss from each page. You may want to reconsider that and go with a SPA. You will likely end up loading everything up front, but you'll load it all only once.

#section syntax instead of requirejs or browserify for angularjs application

I understand that requirejs and browserify can load my files dependent on its current context, and that it is amazing. I would really prefer to use the #section sections syntax that the razor engine uses. Was just wondering if there is a way to implement this into a typescript / angularjs application.
for example
index.html
#renderSection scripts;
// which could turn into something like
<script data-render="scripts"></scripts>
// the app.run() could declare all the scripts that will be needed on every
// page view
view.html
<script ng-section-repeat="injected in injection"></script>
// the ng-section-repeat is basically taking all the items in the
// typescript constructor and then finding out which ones are needed for
// that view.
I like the idea injecting application file dependencies in the view , without a configuration file and all the added extras that comes with the loaders.
I just want to easily define what files are needed in the actual view and get them loaded, with angular's dependency injection handling the dependency itself.
If you are handling all your dependencies with $inject then , as far as i can tell, dependency is technically already setup in the controllers, all one would need, is to load this as it is called. Which could even eliminate the need for the #section scripts completely
Update:
What i have done to sort of replicate the module loaders is to just use gulp-concat and define the file order in my gulp.config.js and then pass it to the gulp-src before running $.concat .this allows me to have the files in the gulp steam , in dependent order . They are however loaded on the first load. With gulp-uglify the files are tiny ( its now at 566Kb with 16 external libraries loading in 69ms . To put that into perspective it takes 209ms to load one google font ).
I dont know maybe i am not understanding browserify correctly but i honestly struggle to see the need for it, its seems extremely convoluted for something so simple
It is possible using external modules and an injector to do what you asked for:
I just want to easily define what files are needed in the actual view
import {UserFactory} from 'models/userFactory';
import {UserValidator} from 'models/userValidator';
import {Inject} from 'angular2/di';
and get them loaded, with angular's dependency injection handling the dependency itself.
Note: My example uses angular 2.x because I less familiar with angular 1.x and I'm sure you can do something really similar...
class SomeComponent {
userName: string;
userRating: number;
rating: number;
constructor(
#Inject(UserFactory) UserFactory
#Inject(UserValidator) UserValidator
)
{
this.UserFactory = UserFactory;
this.UserValidator = UserValidator;
}
}
Then you can use Browserify to create a bundle.js file that can be executed in a web browser.

How to make custom theme in MEAN

I am new in MEAN and going to create new website using MEAN.
I have created the package in MEAN using the command mean package <package_name>
I have also override the default templates using the app.set('views', __dirname + '/server/views'); command in the app.js of my custom package, but the MEAN is still rendering my angular views within the MEAN's default layout.
The structure of my MEAN package folder is
packages
--core
----admin
----articles
----circles
----swagger
----system
----users
--custom
----<my_package>
------public
--------assets
--------controllers
--------directives
--------routes
--------services
--------views
------server
--------config
--------controllers
--------models
--------routes
--------views
------.bowerrc
------app.js
------bower.json
------package.json
----i18n
----theme
How can I render my own theme
To change the layout view to a different one than the default view
In the routes folder under server parent folder, look for the file that has the function mapped to the route '/'.
Now look for that function in the controllers folder. Change the name of the view to render like this:
exports.index = function(req, res) {
res.render('differentviewfile', {
user: req.user || null,
request: req
});
};
To change the look and feel of your site
You can take advantage of numerous Bootstrap themes available out there. A lot of them are free. To use them, all you have to do is change the reference to the css file (you will find it in the server side view base layout page).
Change it from the default bootstrap file to a different one, and your whole app changes. For e.g. take a look at the 16 themes available at https://bootswatch.com You can reference the CDN link to any of the themes they have directly, or you can download the css file for it and add it to your own project.
If you want to add your own styles, you can of course create your own css file and add appropriate css styles.
Did you injected a dependency to system package in your app.js file?
var MyCustomModule = new Module('mycustommodule');
/*
* All MEAN packages require registration
* Dependency injection is used to define required modules
*/
MyCustomModule.register(function(system, app, auth, database) {
You need to do that in order to wait until the system package is loaded. Then the line:
app.set('views', __dirname + '/server/views');
will override the views config set in the system package :D

Angular + Ionic loading all content via XHR

We have an Angular + Ionic app that we are planning on running through Cordova, but having an issue with performance that we are trying to track down.
What we are seeing in Chrome Dev tools Network tab when running either locally or on the built app, is the following:
Duplicate loading of CSS
XHR requests to get every single template file our Angular UI router links to, without having visited the routes yet
As an example:
And line 3167 (indicated with a star) from the angular.js source:
append: function(element, node) {
var nodeType = element.nodeType;
if (nodeType !== NODE_TYPE_ELEMENT && nodeType !== NODE_TYPE_DOCUMENT_FRAGMENT) return;
node = new JQLite(node);
for (var i = 0, ii = node.length; i < ii; i++) {
var child = node[i];
element.appendChild(child); *
}
},
I've never seen anything like it - we've checked all the basics (duplicate script/css includes, etc), disabled Ionic caching, etc.
I'm stripping things down to the studs to see what could be causing this, but hoping someone else has seen this and can offer some advice on where to start looking.
UPDATE
The duplicate CSS appears to be due to our index.html file which bootstraps our Angular App was incorrectly pointed to as a state in the UI Router config.
So the root issue is the spurious/unexpected XHR pulls to all of the static files in the app (angular ui templates, directive templates).
The way I deal with html templates is to cache them all at compile time using gulp-ng-templates or grunt-angular-templates (depending which flavor of task manager you like nowadays).
Since we are dealing with apps, the content should better be eager-loaded rather than lazy-loaded (as long as you count their total size in MB), thus saving some bandwidth and improving the overall user experience. In addition it might just fix your issue.
The beauty of caching the templates at compile time is that your implementation doesn't need to know where they are coming from (server or the caching layer), and thus you don't need to change any code.
P.S. I understand that my answer will not fix your actual problem, but it might just solve 2 issues at the same time.
Well, when a state is activated, the templates are automatically inserted into the ui-view of its parent state’s template.
You should check how you have defined your states. And/or share your state definitions with us :)

Resources