Can Vue import components by dependency inject(DI) like angular? - angularjs

I used angularjs(1.x) and new to Vue.There has DI in angular and refer a service in controller or a directive in template is easy, wherever the service or directive is. Angular will help you inject it automatically.
But I realize Vue refer a component by import(ES6) the path where the component in.If I change the component direcotry structure when refactoring(frequently), there will lost the component refer, and I should fix the path one by one. How troublesome it is.
I know there have a vue-injector like angular DI, but if it is easy to use?

Vue doesn't provide any formal dependency injection mechanism. It's completely up to you how you want to import dependencies.
Most Vue code samples do not use dependency injection at all and just use the ES6 module system via import and export.
If I change the component direcotry structure when refactoring(frequently), there will lost the component refer, and I should fix the path one by one. How troublesome it is.
You probably shouldn't be changing the directory structure frequently. Check out the Vue webpack template for an example of how to correctly structure a Vue project.
That being said, it doesn't really answer your question. Are you using webpack (or something similar)? You can configure precisely how webpack should locate modules via the resolve configuration property, so that you don't have to use relative import paths.
Another way is to register each Vue component globally so you don't need to import them at all.
Another way is to abuse ES6 modules by creating, say, a components.js module which imports each Vue component (wherever they are) and exports them all from that one module. Now you only need to import from that central module instead of hunting down the specific module location of each thing you want to import.
// components.js
import Button from 'path/to/button.vue';
import Alert from 'path/to/alert.vue';
export {
Button,
Alert,
};
// myform.js
import { Button } from 'path/to/components.js';
If you change the location of button.vue, you only need to update the import from inside the components.js file.

If you think you are going to restructure a lot, you can have one file that everyone imports and it imports all the rest, that way you only need to change in one place.
I personally prefer the import over the Dependency Injection, way easier to understand where everything is coming from.

Related

Tree shaking from remote import

This question might seem unusual and a little anti-pattern but at this stage I am just trying to figure out what is possible.
The situation is that I have a few components which are available from a remote import (via Webpack 5's Module Federation). The caveat is that I don't want to lazily load them.
Once imported, the components are passed into a HOC to enrich some functionality and then exported:
import ComponentFooRemote from 'testRemote/Foo'
import ComponentBarRemote from 'testRemote/Bar'
const ComponentFoo = withEnrichedFunctionality(ComponentFooRemote)
const ComponentBar = withEnrichedFunctionality(ComponentBarRemote)
export {
ComponentFoo,
ComponentBar,
}
Functionally this works as expected. The components can be imported, rendered, and no components are loaded twice.
The issue is that the code imported from the remotes are always loaded. If I don't use ComponentBar - or even if I delete ComponentBar - the code from the remote will be downloaded as long as the original import is present. This is happening when using both development and production mode in the Webpack config.
Does anyone know if I can tree-shake these imports or restructure the code to better optimise the performance? Ideally I would like to import the components from the same path.

REACT import css and js files

My application needs to have two pages, one landing page and one admin page. Both pages use different themes. I could not integrate css and js files of these two pages in a single page application.
const jquery = require('mdbootstrap/js/jquery-1.11.3.min.js');
window.jQuery = jquery;
window.$ = jquery;
require('mdbootstrap/css/bootstrap.min.css');
require('template/homePage/js/plugins/owl-carousel/owl.carousel.css');
require('template/homePage/js/plugins/owl-carousel/owl.theme.css');
require('template/homePage/js/plugins/owl-carousel/owl.transitions.css');
require('template/homePage/css/animate.css');
require('template/homePage/js/plugins/YouTube_PopUp-master/YouTubePopUp.css');
require('template/homePage/css/preloader.css');
require('template/homePage/css/style.css');
require('mdbootstrap/js/popper.min.js');
require('mdbootstrap/js/bootstrap.min');
require('template/homePage/js/plugins/vivid-icons');
require('template/homePage/js/plugins/owl-carousel/owl.carousel.js');
require('template/homePage/js/plugins/YouTube_PopUp-master/YouTubePopUp.jquery.js');
require('template/homePage/js/plugins/wow/wow.js');
require('template/homePage/js/plugins/jquery.easing.min.js');
require('template/homePage/js/main');
this sample import not good work. And I need outside link css and js.
I have two problem one of them is $(...).scrollspy is not a function
other WOW is not a function.
None of them work in sequence.
When you want to import resources into your React app, you use imports like this:
// Import with variable assignation
import logo from './logo.png';
// Import without variable assignation
import './css/index.css'
You can read more about this in the create-react-app documentation:
https://create-react-app.dev/docs/adding-images-fonts-and-files/
You can read more about ES7 imports here:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import
I see what you're trying to do is to add libraries and resources to your app component, like if were a common html file, you can't do that in React , you need to find an implementation.
It is not recommended to use jQuery with React, because you use jQuery to write code in a simple and fast way to create complex implementations, now those complex implementations can be made with just React and JS, that is what React is designed for.
Now I understand that you might want to use jQuery even do is not that recommendend, so here is a link where you can get jQuery to install it as a plugin for your React app
https://www.npmjs.com/package/jquery
You would be able to import it to your component like this:
import $ from "jquery";
To use Bootstrap in your React app you check out the documentation of an implementation of Bootstrap for React, react-bootstrap:
https://react-bootstrap.github.io/getting-started/introduction

React tree-shakable component library with Rollup and Sass

I have a requirement which I'm not sure if can be achieved with Rollup (or with Webpack?)
I've written a React component library. Each component imports it's stylesheet. Something like
import "./button.scss"
export default function Button() {
...
}
Now, these scss files use sass variables of all sorts that I would like to define in a global file.
I want the consumer of my library to be able to import Button as so:
import { Button } from "mylib" or even better:
import Button from "mylib/button"
and have only the code required by Button be added to my library.
I can't for the life of me figure/google out how to achieve this.
Is there a good reference to a tree-shakable React component library that uses sass and sass variables?
Bonus question:
I have some third party css that only some of the component require.
So, if each of the component's scss files imports:
#import "~some-third-party-css-lib.css"
Will Rollup duplicate that css? Or is there some kind of deduping mechanism?
Thanks!
From what I know now (Feb 2020) the only options to achieve good tree-shaking results for a component library are:
When using css modules
You need to rely on the consumer of your library to handle the (s)css imports (Create React App for example is doing this pretty well)
Make sure to not transpile/bundle the css in your package and that the import paths are correct
Make the consumers import each component separately (import Button from "mylib/button"). This is because css imports are considered side-effects by most bundlers and it's petty hard (maybe even impossible) to tell which classes are actually used. So if you have an index in your library that re-exports all components, this causes ALL css to be imported and probably bundled.
When using a css-in-js system with a runtime
also make sure that you do not pre-bundle/export the css in the library build-step but rather have that leave that to the consuming app.
This has some implications that should be considered.
The consumer of your components must ship a css-in-js runtime alongside their app
If the consumer is trying to do server-side pre-rendering in some sort that might require custom additional steps depending of the css-in-js library you're using
Conclusion
As of now I don't know a solution that supports full tree-shaking (including css) while also not imposing additional complexity to the consuming app. But I'm currently still investigating this topic and will post updates here if I find something interesting.
Look at the library tailwindcss. It automatically purges the unused css variables.

How to Use Internationalization with element-react

I've created a react application using create-react-app, and installed element-react as a dependency. I followed the instructions stated here to use internationalization -- specifically adding these lines of code to what I think is the entry file (App.js):
import { i18n } from 'element-react'
import locale from 'element-react/src/locale/lang/en'
i18n.use(locale);
Unfortunately, this doesn't work. The other approach stated is using webpack but I don't want to do that. How do I make internationalization work with element-react? What is the entry file in a react application?
Actually, it did work when I placed the il8n code in index.js. It just doesn't seem to work for tables when they don't have data. The workaround for that is to set the emptyText property of the Table component.

AngularJs and Webpack - How to import services, components and modules

I've started using webpack in quite a large code base and have been using ES6's import statement to load the required dependencies for each module.
My file structure aims to be component based, with all the pieces specific to a component inside that component's folder. For example, the component file itself, and then templates, stylesheets, services, filters, etc, also specific to that component. Then we may have a generic service folder inside that module for services that are not specific to a particular component. eg:
- my-module
- component-a
- component_a.component.js
- component_a.component.spec.js
- component_a.html
- component_a.scss
- services
- some_service.service.js
main.module.js
main.run.js
main.config.js
My problem is that the main.module.js file is becoming unmaintainable, as I manually import all the required dependencies into this file and then register them into the angular world as required. eg:
import componentA from './component-a/component_a.component';
import someService from './services/some_service.service;
angular
.module('myModule', [])
.component('componentA', componentA)
.service('someService', someService);
You can imagine what this starts to look like when you have 10+ components. I've struggled to find a good solution for this problem, does anyone have any suggestions? Is there a best practice approach here?
I guess, every component/controller/service etc. can connect itself to the app in their own file.
Like you have got a file ome_service.service.js and inside you write:
myApp.service('omeService', function(){
var app = this;
// service stuff
});
So the registration is not in your main.module.js but in every file itself.
Although, you need to expose your app variable to be globally available. With a bundler like webpack this is easily handled. Gene Conroy-Jones wrote a nice post about how to make it possible via webpack here: https://medium.com/#drgenejones/using-webpack-with-legacy-angular-spas-automating-imports-using-require-context-58e0e9cc6e9c
With this approach, every new component would handle its registration on their own, and the central app would not have to carry all those imports.

Resources