I'm using storybook to be the showcase of different components. However I've found that the context of different components in storybook are not separated. E.g. in one of the story, I register the mocked services in the Dependency Injection, and in another story, I will get the already injected mocked services from the previous story.
I've also found that the CSS files being imported are also being kept in the memory. If there is some global CSS styles, once it is being imported in the first story, I could also get it in the second one without import it again.
However this is causing problems, e.g. the Dependency Injection library will complain that a service is being injected twice.
It seems that all the stories in the storybook shares the same global context. Is there any way to separate the context, so that each of the stories has its own context which is getting destroyed each time when people switch the story?
Please let me know if you need any extra information, e.g. storybook configuration or so.
Thanks in advance.
Related
In my workplace I've been told by my supervisor to use autoloaders instead of using many import statements since it's slow! First of all, based on my research there are no performance benefits of doing so and secondly(I'm using js modules, and we are not talking about bundles), I can't think of any good reasons for doing such thing.
The way my imports work now are:
Imagine we import a.mjs like so ->
import '/js/components/a.mjs'
The route /js/ is a rule that redirects to my root of static js files, so I don't even need to use relative paths.
Is it bad practice? If there is something that I'm missing anything please tell me; I've done my research and didn't find any reasons to use autoloaders with js modules.
An actual example for you to see:
Flask route rule:
#app.route('/js/<path:filename>')
def js(filename):
return send_from_directory(Path(app.root_path).parent.absolute().joinpath("static\\js"), filename)
and in my js files:
import {View} from "/js/common.mjs";
import Spinner from "/js/components/spinner.mjs";
import RecommendedTripsSlider from "/js/components/recommended-trips-slider.mjs";
import TripsSlider from "/js/components/trips-slider.mjs";
import Blogs from "/js/components/blogs.mjs";
Thank you for your time. I appreciate it.
From the JavaScript Modules Guide on MDN :
Modules are only executed once, even if they have been referenced in multiple <script> tags.
This can be verified in the spec under section 16.2.1.5.2 Evaluate.
Evaluate creates and returns a Promise which resolves when the module has finished evaluating. This Promise is stored in the [[TopLevelCapability]] field of the [[CycleRoot]] for the component. Future invocations of Evaluate on any module in the component return the same Promise.
The first time the browser needs a module, it is hoisted, loaded, cached and executed. Additional import statements in future scripts will reference the pre-evaluated module from memory. No additional HTTP requests need to be made. No additional execution needs to happen.
On subsequent page views, the locally cached version of the module will be used, assuming your server's caching policy is configured appropriately, or you've implemented caching with a service-worker. In fact, you can even preload any specific modules that you might need ahead of time.
Performance-wise, as long as your app isn't importing hundreds of modules you should be fine. At that point you should probably look into bundling related components together with tree shaking. However, monolithic app bundles should be avoided as they obliterate the benefits gained from using modules since one small change to a single component means your users now have to re-fetch the entire app. Keeping your components split up means that user agents only download the parts needed to display the content on the page they're on and nothing more.
One reason you might want to use a module loader/bundler would be if you were installing dependencies through a package manager like npm. Then you would need a way to resolve the named imports to their actual file paths. But that process can easily be handled without a build step by using import-maps.
<script type="importmap">
{
"imports": {
"moment": "/node_modules/moment/src/moment.js",
"yourlib": "/lib/yourlib.js"
}
}
</script>
Unfortunately, this feature is not available in all browsers yet but. This already works in Chromium based browsers, has recently been implemented in Firefox (slated for release in v102) and support for other browsers can be polyfilled with es-module-shims.
This is the future of native module resolution. Implementing an autoloader into your project now would be a step backwards.
I have an Agular app with several lazy-loaded modules. These modules each contain some different components which are logically similar but differ in content. E.g. each module may have its own "home" component.
Is it okay to name these components exactly the same?
To me, it seems overly verbose to prefix each with the module name. Especially when the names start to get long, and considering I would like to maintain the balance between concision and readability.
Functionally this doesn't appear to be a problem. Take the following app as an example. It has 2 lazy loaded modules each containing 2 components with the same name as the components in the other module. One component is loaded by the module's route and the other is loaded via its selector in the template of the first component.
https://stackblitz.com/edit/angular-comp-name-test
I understand that this question may be considered as opinion-based but are there any technical reasons why this shouldn't be done? (I am also interested in opinions if someone wants to dm me)
Technically there is no issue, you can use the same name. Like I have many modules having dashboard as each respective module's component. As long as you properly import it, its fine.
But for larger apps sometimes when auto importing it can import pointing to different 1 then the one required. This happened with me once, I had add and list component in 2 different so while auto importing the url was pointing to the wrong one.
So for just the sake of clarity its nice if you keep different name like prefixing it with something so you know it is for this module etc otherwise we can't say it is or is not "good or bad practice".
Hey you can use import aliases in the tsconfig.json paths
"paths": {
"#modules": "app/test-mod(?:\.\d+)?"
},
You can use regex to match the file end names so that if you have more than one folder you can just name them like file1, file2, file3 and son on the match them in the import using
import('#modules/innerfolder/mymodule.ts')
I have been working on a project with 5 lazy loaded modules having millions of components in their sub folder with same components names.
The good reason or the problem faced by me in while in the development only is while importing the components the auto import does some time imports component from different module and that way I have been facing confusion and getting development done some time with wrong components.
But this has happened 2 times after then I was very safe while importing components
In a multi-tenant project, tenants could have different UI and functionality. To that end, there is a structure like this:
TenantA
SiteHeader.ts (class named SiteHeader)
TenantB
SiteHeader.ts (class named SiteHeader)
... 20 other tenants
On the web page, the .js declaration dynamically generates (server-side) the reference to the correct tenant:
<script src="../{CurrentTenant}/SiteHeader.js"></script>
On this same page, Main.ts needs to reference the correct SiteHeader. Since I can't (and don't want to) have import {SiteHeader} from 'TenantA/SiteHeader' and import {SiteHeader} from 'TenantB/SiteHeader' and 20 others, I am forced to simply declare it as a var, which points to whatever js was loaded by the parent page:
declare var SiteHeader;
However, it causes Duplicate identifier errors in each SiteHeader.ts. And occasionally in the Main.ts as well. I am able to drop down to the command line and compile each SiteHeader.ts manually, but it's chore.
How can I resolve this sort of situation?
Not that it matters much, trying to bring TypeScript to an old school WebForms project in Visual Studio 2019.
You could create interface SiteHeader and make all tenants implement it. But I am not sure how runtime would work with <script> tag in combination with external modules. Have you considered internal modules (namespaces) or using dynamic import() (should be supported in TypeScript)?
I would like to add a Javascript function to all pages within the store that installs my module.
I read up on hooks, and it seems that there's no single "display" hook that I can count on being called for every single page in the store - different pages have different hooks. E.g. I need to use the displayHeader hook for "Home page and general site pages" but this doesn't work for product pages.
Is there a way to do this with a single hook, not a list of hooks each for a specific page category?
Note that I don't want to use a theme for this, because my module is meant to be an add-on to the store, not an overarching design template.
Edit:
I was wrong saying that displayHeader hook doesn't work for product pages. Indeed, as the answer says, that's the one that I need to use.
you still can use this call
$this->context->controller->addJS($this->_path.'your.js');
in module hookDisplayHeader() method, it will register your js file in js files list that will appear in e.g. header.tpl loop by $js_files
P.S.
also do not forget about mobile with somethign like:
public function hookDisplayMobileHeader()
{
return $this->hookHeader();
}
so module should be registered in 2 hooks Header and mobileHeader to appear on all devices.
I'm having an issue thinking about the best way to architect a React app with multiple pages/views (still a SAP).
Let's say we have a simple app with 4 major sections (pages): dashboard, users, stats, comments. Each section has different components in it (think react components). For example, the comments section would have a hierarchy like so:
CommentsSection
- CommentsQueue
-- Comment
--- Text
--- Buttons
- CommentsApproved
--Comment
--- Text
--- Buttons
In a framework like angular for example, the 4 main sections would be split into partials, and loaded in an ng-view upon request, with their respective components inside. When landing on the homepage, the app would only load the dashboard view and upon the user clicking on a nav item, the selected route (i.e. app/users or app/users/:id) would trigger and the app will load the required "template-view-partial" (without a browser refresh).
Now in terms of React, how would this occur? it seems like ALL views and ALL their components would need to be available in a browserified JS file and the app can then update the DOM.
This seems terribly wrong, as we'd be loading all sections in the first load, even if the user doesn't ever need to get to that section. Granted, we could split it with routes on the server, and only serve the components for the page based on the route, but that would require a browser refresh, where as in Angular for example, it would happen without a browser refresh as the view is loaded asynchronously.
The question is, how can this asynchronous loading happen in a React-based app?
I think there's a few different ways in approaching this, I'll explain the approach that I am currently using for my work and side projects.
Instead of using browserify, we use a module-bundler called webpack (https://github.com/webpack/webpack). What's great about webpack is that it's like Browserify but can split your app into multiple 'bundles'. This is great because if we have multiple components/views, the user would just download the features they need for that particular view without having to download everything initially. It allows react-components and their dependencies to be downloaded on demand.
Pete Hunt wrote an article that goes into depth on the benefits of webpack when using it with React (including how to async load react components), and how it is similar/different to Browserify and modern build tools like Grunt/Gulp: https://github.com/petehunt/webpack-howto
I have described one solution using webpack here : http://blog.netgusto.com/asynchronous-reactjs-component-loading-with-webpack/
In essence :
use require.ensure([], cbk) to define code chunks; in the cbk, load your packages synchronously using require()
in your host component, load your asynchronous component in componentWillMount(), and set in in the host component state.
use it in the host component render, when defined on the state