How to properly build a Vue component library using Vuetify - javascript

I've done my research and found some questions about building a vue component library using vuetify. However none of them answered my issue.
After building the library and adding it to my app, the app throws errors of unknown custom elements. These elements are the vuetify ones.
Here is my small lib:
https://codesandbox.io/s/staging-water-f79hp
What am I doing wrong?

You have to import the Vuetify components and add them to the components section of your own components.
For example:
<script>
import VFileInput from 'vuetify/something'
export default {
name: 'FormParser',
components: {
VFileInput
}
}
</script>

Related

React - storybook. Bootstrap Icon components don't show in storybook

I am building React storybook components using react-bootstrap.
Almost components are completed well.
But only some components that includes bootstrap icons don't show in storybook.
Is there any way to fix this issue?
Thanks.
Sometimes the issue is for linked components, in this case, you need import each icon from SVG.
import {
faEdit,
faUser,
faCartShopping,
faHeart,
} from "#fortawesome/free-solid-svg-icons";
Don't forget link the components in console with: npm link
import "bootstrap-icons/font/bootstrap-icons.css";
in the .storybook/preview.js file solved that issue.

Nuxt plugin imports abuse vendors

I am trying to use vuejs-datepicker in a nuxt app, everything is done by nuxt plugin usage standarts.
plugins/vue-datepicker.js
import Vue from 'vue'
import Datepicker from 'vuejs-datepicker'
Vue.component('Datepicker', Datepicker)
nuxt.config.js
plugins: [
{ src: '~/plugins/vue-datepicker', ssr: false }
],
But even when it is not used I am getting its dist uploaded in the vendors/app....js after the build. How can make nuxt create a separate chunk for it and import that chunk only in the pages which are using it?
So yeah, there is basically a feature request open for this kind of use-case.
But looking at the Nuxt lifecycle, it looks like the plugins are imported even before the VueJS instance is done. So, you cannot lazy load it if it's done ahead of Vue.
But, you can totally import vuejs-datepicker on the page itself, rather than on the whole project. This may be enough
import Datepicker from 'vuejs-datepicker' // then simply use `Datepicker` in the code below
If it's not, you can maybe try this solution: https://github.com/nuxt/nuxt.js/issues/2727#issuecomment-362213022
// plugins/my-plugin
import Vue from 'vue'
export default () => {
// ...
Vue.use(....)
}
// adminLayouts
import myPlugin from '~/plugins/my-plugin'
export default {
created() {
myPlugin()
}
}
So, the downside is that you have to import the component each time that you need it rather than having it globally but it also allows you to load it only on the concerned pages too and have it chunked per page/component.
If you were trying to find a way to split the component from vendor but you were getting a document is not defined error you can use this syntax to import your component, it will create a separate chunk with your component and use it only in client-side.
components: {
Datepicker: () => import('vue-datepicker')
}
Also, it would be helpful to wrap your component in <client-only> tag for most of the cases.
The plugin I was trying to import used window. For this reason, any other suggested workaround still caused nuxt to crash or error in my case. I searched the whole wide web and the solution below is the only one that allows my app to run.
Instead of importing the plugin with an ES6 import, you can import it in your mounted hook, which should run in the client only. So:
async mounted() {
const Datepicker = await import('vuejs-datepicker');
Vue.use(Datepicker);
}
I do not know about the specific plugin you are trying to use, but in my case I had to call Vue.use() on the default property of the plugin, resulting in Vue.use(MyPlugin.default).

Next.js routing error in website tutorial

For me the next.js tutorial https://github.com/zeit/next-learn-demo.git
has a problem at all stages past stage 2 "dynamic routing". Even though in the stages afterwards on stages 3 to 8 the dynamic routing should already be working.
What i assumed was the problems is that the file .next/routing appeared to be missing.
As such the tutorial asked implementation of code:
import { useRouter } from 'next/router';
and
const router = useRouter();
does not do anything.
leading to the error on clicking the link:
screenshot of next.js browser syntax error inspection
Why is the routing file not in the .next folder?
the react version is 16.10.2 (installed today through tutorial instructions)
the format of code is what is in the tutorial copy pasted. (no hook rule breaking)
there are no react duplicates.
I think you are using useRouter() in class component. useRouter is a hook and used only in functional components.
in class components we use withRouter HOC. "router" object is accessible as
this.props.router

Importing external React components to nextJS project

I have a functional component in my own library that I'm importing into a nextJS project, and for some reason it's not recognized as a react functional component.
Example of my library code:
import React, { useState } from 'react';
export function Dialog(){
const [open, setOpen] = useState(false);
return (<>
// some jsx logic
</>)
}
importing it in my nextJS component:
import { Dialog } from '#myNamespace/library';
When I try to use
<Dialog />
I get this error:
Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See https://reactjs.org/warnings/invalid-hook-call-warning.html for tips about how to debug and fix this problem.
So I logged out a local react component with the Dialog and found that while the local react component seems to be on the namespace react__WEBPACK_IMPORTED_MODULE_1___default, my imported component just remains a plain function instead of a react component.
Any ideas as to why NextJS isn't importing my function as a react component?
EDIT:
Here's something really interesting: When I remove the hook, nextJS seems to think it is a react component. But when I put the hook in, it doesn't - and throws that error.
SOLUTION
For anyone who's interested - the issue was that my package was npm link into my project. So in that case there's issues with it not packaging up the components correctly.
It is possible that your react and react-dom isn't updated to the standard for hooks try yarn add react#18.6 react-dom#18.6

Dynamically loading React components

I'm thinking about building a web application, where people can install plugins. I'd like plugins to be able to define React components that will be rendered to the page, without recompiling the main JavaScript bundle after installing the plugin.
So here's the approach I'm thinking of:
Bundle the main JavaScript with React as an external library, using webpack.
Have plugin authors compile their components with React as an external library as well.
This way, I'm only running one instance of React. I could probably do the same with some other frequently used libraries.
The problem then, is how to dynamically load these plugin components from the server. Let's say I have the following component:
class PluginRenderer extends React.Component{
componentWillMount() {
getPluginComponent(`/plugins/${this.props.plugin}/component.js`).then((com) => {
this.setState({pluginComponent: com});
})
}
render() {
var Plugin = this.state.pluginComponent;
return Plugin ? <Plugin {...this.props} /> : "Loading..."
}
}
How could getPluginComponent be implemented?
It's an interesting problem I also faced some months ago for customer work, and I didn't see too many document approaches out there. What we did is:
Individual plugins will be separate Webpack projects, for which we provide either a template or a CLI tool that generates project templates.
In this project we define Webpack externals for shared vendor libraries already used in the core application: React, Redux, etc. This tells the plugin to not include those in the bundle but to grab them from a variable in window we set in the core app. I know, sounds like sucks, but it's much better than having all plugins re-include 1000s of shared modules.
Reusing this concept of external, the core app also provides some services via window object to plugins. Most important one is a PluginService.register() method which your plugin must call when it's initialized. We're inverting control here: the plugin is responsible to say "hi I'm here, this is my main export (the Component if it's a UI plugin)" to the core application.
The core application has a PluginCache class/module which simply holds a cache for loaded plugins (pluginId -> whatever the plugin exported, fn, class, whatever). If some code needs a plugin to render, it asks this cache for it. This has the benefit of allowing to return a <Loading /> or <Error /> component when a plugin did not load correctly, and so on.
For plugin loading, this PluginService/Manager loads the plugin configuration (which plugins should I load?) and then creates dynamically injected script tags to load each plugin bundle. When the bundle is finished, the register call described in step 3 will be called and your cache in step 4 will have the component.
Instead of trying to load the plugin directly from your component, ask for it from the cache.
This is a very high level overview which is pretty much tied to our requirements back then (it was a dashboard-like application where users could add/remove panels on the fly, and all those widgets were implemented as plugins).
Depending on your case, you could even wrap the plugins with a <Provider store={ theCoreStore }> so they have to access to Redux, or setup an event bus of some kind so that plugins can interact with each other... There is plenty of stuff to figure out ahead. :)
Good luck, hope it helped somehow!
There is a HOC component that you can import to do this. Components are dynamically loaded as micro apps into your host application.
// index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
window.React = React;
window.ReactDOM = ReactDOM;
ReactDOM.render(<App />, document.getElementById('root'));
// app.js
import React from 'react';
import ReactDOM from 'react-dom';
import MicroApp from '#schalltech/honeycomb-react-microapp';
const App = () => {
return (
<MicroApp
config={{
View: {
Name: 'redbox-demo',
Scope: 'beekeeper',
Version: 'latest'
}
}}
/>
);
});
export default App;
The components are not installed or known at design time. If you get creative, using this approach you could update your components without needing to redeploy your host application.
https://github.com/Schalltech/honeycomb-marketplace#using-micro-apps
I presented an alternative approach on a similar question. Recapping:
On your app
import(/* webpackIgnore: true */'https://any.url/file.js')
.then((plugin) => {
plugin.main({ /* stuff from app plugins need... */ });
});
On your plugin...
const main = (args) => console.log('The plugin was started.');
export { main };
export default main;
See more details on the other question's page.

Categories