I am working to give my Angular 1.5 apps an upgrade with ES6 classes and I've been following Todd Motto's styleguide pretty closely so far. I have been naming component files like so:
|-components/featurename
|---featurename.index.js
|---featurename.component.js
|---featurename.controller.js
|---featurename.service.js
|---featurename.style.css
I have been naming classes like so:
const SomeComponent = {};
export default SomeComponent;
And then importing with the same name:
import SomeComponent from './featurename.component';
I'm wondering if dropping the featurename from all of this is going to cause problems with testing and debugging. It would certainly make creating feature boiler plates easier without a generator. I am proposing something like this:
|-components/featurename
|---index.js
|---component.js
etc..
const Component = {};
export default Component;
import Component from './component';
I believe you are free to orginize the sources in your project in a way you like to see them. The "featurename" prefix is useful for file-searching. I think this is the main point here. Let's imagine, we have 10 features, it means that we have 10 index.js files. Searching for "index" as a filename + "js" as an extension would give us 10+ results... in that case will have to search for feature specific folder. It may depends on the environment you are using for the development, there may be such a setup where it's not an issue.
Related
When using autoimport feature of nuxt3:
is there any impact (types, performance, bundle-size, tree-shaking, etc..) of using the # alias to import something rather than no import at all?
Or its only purpose is to make imports explicit and maybe help to fix some IDE/linter/ts issues?
Example:
// plugins/vuetify.ts
import { createVuetify, VuetifyOptions } from "vuetify";
import { defineNuxtPlugin, NuxtApp, Plugin } from "#app"; // this line should be optional
export const VuetifyPlugin: Plugin = defineNuxtPlugin((nuxtApp: NuxtApp) => {
const vuetify = createVuetify();
nuxtApp.vueApp.use(vuetify);
});
export default VuetifyPlugin;
I wasn't aware of the # import, do you have a reference for that specifc one?
As you kinda guessed it, there are no direct benefits of making the imports yourself. In the same way that Nuxt does the job for you regarding ref, computed, watch etc, it will try to import most of the other common stuff.
The compiler will scan your file, see what you are using in your template + script part and make the import himself on runtime. It may not guess fully dynamic imports (usually for components based on a dynamic variable for example).
Still, it should work in the exact same way performance-wise.
For the types I know that there could be some limitations (not a full coverage), but since I don't use TS, I'm not well aware of all the details.
Regarding IDEs/code editors, most of the time they will work fine but some of them may require a bit of configuration to work perfectly (since it's implicit, you still need to tell your editor what is happening), otherwise some Linters may complain a bit.
Nuxt's auto import feature is probably based on something really similar (if not identical) to this: https://github.com/antfu/unplugin-auto-import
Hence, you can see in details how this one works to get more explanation.
I would like to use javascript classes with one class per file. It is part of a larger project using eslint. I started with:
/*global CSReport*/
/*global CSManager*/
class CSMain {
constructor() {
this.report = new CSReport();
this.manager = new CSManager(this.report);
}
launchReport(...
}
However, eslint generates an error saying CSMain is defined but never used. This led to the idea of using export and import which seemed better than making everything global (side note: CS in front of main is the old style method to avoid global conflicts)
The question is how to put this together. The release version will be a single (uglified) file, so the class file names will no longer exist when they are all concatenated together in (say) csCompiled.js.
Questions:
Import uses a file name. Should I use the CSCompiled.js name rather than the file names before concatenation?
Do I want a single module or a module for each class?
Do I need to export every class and import every class it uses?
I am not fully sure how angular accesses this code but am thinking to import csMain.
I tried to find an answer to this but am only finding older posts that don't use ecmascript 6 and classes. If an answer to this exists, I am not sure how to get to it.
Background:
The main project uses angular 1. This code is separate for legacy reasons. It is currently written in java using gwt, but we want to move to javascript to remove the reliance on gwt. It is about 30-40 files (classes) total to convert.
The code gets and handles data from the server for report requests. There is a lot of pre-processing done before it is handed back to the rest of the UI.
I have used javascript for an established project using angular, but lack expertise on how to create new projects.
I am trying to use basic javascript for this, so it won't need updating if (for example) we go from angular 1 to the current versions. I do not yet know if this is a good way to do it.
ESLint is complaining because you are not exporting the class you created, therefore, it can't be accessed by other modules. You can fix that with a simple line at the end
export default CSMain;
Import uses a file name. Should I use the CSCompiled.js name rather
than the file names before concatenation?
Use the file name before you compile/transpile/uglify/etc. After that it will all become 1 file and the bundler will take care of that for you.
Do I want a single module or a module for each class?
Completely optional, I like to have 1 class per file and then 1 file for the module (index.js) that lists all classes in that module.
Do I need to export every class and import every class it uses?
Yes, you need to import everything your module will use and export everything that should be public or "importable" for other modules.
I am not fully sure how angular accesses this code but am thinking to import csMain.
It all depends on how you export your file. Make sure to import the same name your module/file is exporting.
When renaming a React component, how do you ensure the new name is used everywhere?
E.g. OldComponent -> NewComponent
The IDE I'm currently using (IntelliJ IDEA) only part does the job. For example, it will leave the variables with the old name in import statements:
import OldComponent from 'components/NewComponent.jsx'
...
<OldComponent />
Do people generally avoid refactoring in JS, or are there solutions/tools that can do this? (Or do people just kinda get used to manually refactoring? :D)
I think that Shift + F6 should do the job. It does the renaming for all matching cases. You could also find this in context menu -> Refactor -> Rename...
For me personally, the solution was to use TypeScript.
IntelliJ will automatically update the imports for you (if you use TypeScript).
I have gone down a path of using Angular2 but writing ES5 code, which means that the examples and guidance I find usually must be translated from answers relevant to TypeScript.
Can someone help me with an ES5 version of:
Bootstrapping the application. In TypeScript I see it done as:
import {WORKER_APP_PLATFORM, WORKER_APP_APPLICATION} from "angular2/platform/worker_app";
import {platform} from "angular2/core";
platform([WORKER_APP_PLATFORM]).application([WORKER_APP_APPLICATION]).bootstrap(myApp)
Accessing the web_workers component:
import {Component} from 'angular2/web_worker/worker';
#Component({ ... ])
I assumed the latter would be achieved by calling
ng.web_worker.worker.Component({ ... })
But that seems to not be the case: ng.web_worker is undefined.
The problem might be that I seem to not be able to include web_worker/ui.js properly. When I include it instead of bundles/angular2-all.umd.js I only get error messages about require being undefined. When I explicitly include RequireJS in my project I get a bunch of other errors.
Any help will be greatly appreciated!
Can I ask, why do you want to do it with ES5? You can easily use SystemJS and ES6 if you don't like Typescript. Typescript would be almost identical to ES6.
In case you still want to do it with ES5, you need to change the imports to require calls:
var WORKER_APP_PLATFORM = require("angular2/platform/worker_app").WORKER_APP_PLATFORM;
var WORKER_APP_APPLICATION = require("angular2/platform/worker_app").WORKER_APP_APPLICATION;
var platform = require("angular2/core").platform;
platform([WORKER_APP_PLATFORM]).application([WORKER_APP_APPLICATION]).bootstrap(myApp)
Another example:
var Component = require('angular2/web_worker/worker').Component;
You get the idea. You also don't need RequireJS... You can use SystemJS. You should import the main file like this:
System.import("main")
SystemJS will resolve all the require calls async, but in the code, the require calls look sync.
In the ember-cli documentation it describes bridging the addon within your host application by overriding the app/component/[addon-name.js] yourself. However, the documentation doesn't explicitly state how to do this.
With trial and error I've noticed that by creating a component file in your [host app]/app/component/[name of addon.js] and simply copy/paste the addon code into there provides a venue to customize the addon. However, this is a terrible approach, I would imagine that I could simply override the functions in question...and in some cases call this.super().functionName in order to keep the over-rides simple and trim.
However, I can't get this to work. Any ideas?
Extensibility is why addons have both the addon/ and app/ trees. In the app tree for a component, the component should just be an import and export, for example:
import XSelect from 'emberx-select/components/x-select';
export default XSelect;
Source: https://github.com/thefrontside/emberx-select/blob/master/app/components/x-select.js
In this kind of case you want to create the component in [host app]/app/component/[name-of-addons-component.js] then in that component do:
import XSelect from 'emberx-select/components/x-select';
export default XSelect.extend({
//any overrides
});