Creating a custom Javascript Library at build-time - javascript

Background
I have a javascript library that runs on a customers website. This library is a mixture of standard components (error handling, message passing, etc), and per-customer based custom components (specific dom handling routines).
Problem
I am breaking DRY. For each customer, I have the same code duplicated. Since I violate DRY, I am stuck with all the pitfalls: e.g. if I need to make a change to a common component, I have to replicate that change across multiple files.
Desired Solution
I'd like to separate out all the functionality into components, and selectively choose (via build script) the components that get added into the library.
This would be somewhat similar to how Bootstrap allows you to mix and match javascript plugin functionality
Example: CustomerA's library, needs the Base Component, the Comment Component, and a custom handler to parse Google Analytics.
CustomerB's library, needs the Base Component, and a custom handler for their shopping cart experience.
I think I can do this with RequireJS, but is there a more industry standard way to build customized javascript libraries?

I came across Browserify, which allows you to use Nodejs module system to create reusable components, in addition to using NPM node modules.

Related

Embedding Vue Apps (or Vue Web Components) in a non Vue web application

I'm very new to Vue and have been given a task of looking at creating some Vue widgets that could be embedded in a couple of existing non Vue legacy web applications. The idea is that we would create a library of these widgets which could be then embedded in either of the legacy applications and eventually we might migrate the entire apps to Vue.
I've been searching for the best way forward and I am a bit confused. I guess these are my questions:
Do I need to be thinking Web Components here or can the widgets be actual Vue applications that we embed somehow?
If the widgets should be created as Web Components is there any difference between using the Vue/web-component-wrapper or the vue-custom-element library?
Whichever option we choose can we make full use of features that you would use in any normal Vue application - Vue router, Vuex for state management etc (and can state be shared across those widgets)?
Would the widgets need to be fully styled or would it be best practice to leave all the styling of the components to the parent app (or a combination of the two)?
I've never done anything like this before (as you can probably tell!) so any guidance or advice or pointers to examples would be appreciated.
** Update **
I found this article which I think is the direction I need to go in https://itnext.io/vuidget-how-to-create-an-embeddable-vue-js-widget-with-vue-custom-element-674bdcb96b97
There are three distinct (but quite similar) cases:
web components
They are supposed to be an encapsulated web fragment. If you want, it's a smarter alternative to <iframe>s. Its main use case (and what it was designed for) is to display ads in a page and guarantee the host can't mess with its internal logic and rendering.
custom elements
These are, simply put, declared and registered custom HTML tags. The advantage of using them is being able to mark them as off-limits in any outer framework, stating: "this custom element is not one of your custom components, treat it as an HTML tag".
framework components
By default, modern JS frameworks (Angular, React, Vue) use this pattern internally: their internal components look like custom elements (case 2). But they are not. They are just internal conventions, without ever making it into the HTML markup output of the app.
Here's what happens internally: when the template is parsed, if an unknown HTML element is met, the framework assumes it's one of its registered components. If it is, the tag is not rendered. A new instance of that component is created and the tag is replaced with the contents of the component's template (or the result of its render function).
All of the above frameworks, when running into an unknown html tag that is not a registered custom component will issue a warning along the lines of "hey, did you forget to register this component?". Unless it's registered as a custom element (case 2) - in which case they treat it as as such: an HTML tag.
Vue handles all of the above with grace. What you choose for your widgets largely depends on context and desired end result.
Here are the answers to your questions:
Do I need to be thinking Web Components here or can the widgets be actual Vue applications that we embed somehow?
You shouldn't go with Web Components if you want to be able to style them from the context.
If the widgets should be created as Web Components is there any difference between using the #vue/web-component-wrapper or the vue-custom-element library?
Yes, there is. #vue/web-component-wrapper produces web components (encapsulated DOM framents).
vue-custom-elements declares and uses custom elements (custom HTML tags). Their content is HTML markup (not encapsulated). The advantage of using custom elements is being able to inform outer frameworks: don't treat this custom element as one of your own components, it's handled by something else (Vue, in our case). Treat it as HTML markup.
Whichever option we choose can we make full use of features that you would use in any normal Vue application - Vue router, Vuex for state management etc (and can state be shared across those widgets)?
Yes. Whichever option you choose, you're still using JavaScript (every widget/app has unrestricted access to the entire context). You can also inject dependencies into your widgets, allowing them to communicate (by modifying the same external dependency - a router, a state management module, etc...). This is pretty much the standard mode in which every Vue instance normally operates. In simpler words, a Vue (sub-)component can function without a parent component and is, essentially, a Vue app. (or, if you prefer, every Vue app is a Vue instance and all of its sub-components are also Vue instances).
Would the widgets need to be fully styled or would it be best practice to leave all the styling of the components to the parent app (or a combination of the two)?
It's entirely your code design choice. It's easy to scope CSS in Vue. But there are great advantages in styling from above (DRY-er code). Also, having styles coming from context means less CSS rules applying, although that hardly qualifies as a performance issue. Obviously, take into consideration the answer to the first question.

CreateReactApp: embed end-user plugin at runtime

We have a React application created/deployed using CreateReactApp.
This application is able to display some widgets. We've predefined types of widgets deployed with our own application. We'd like the end-users of our application to be able to develop their own type of widgets - using a dev tool like Webstorm/VisualStudio - and deploy them into our application.
Our application needs to provide a public API and a plugin dev library
We want the plugins to be able to use the libraries our application is using (e.g. React, material-ui…)
We need a way to "load" end-user code that is registering new widget types using our public API.
Can we do that using CreateReactApp or do we need to eject?
What are the best practices for doing this?
I have more a suggestion than an answer, a best practice for that can depend on the structure of your current project, so I don't think there's a right answer. I wrote a small proof-of-concept, feel free to fork and use that, if it helps: https://github.com/anderick/react-dynamic-components.
Our application needs to provide a public API and a plugin dev library
To solve this you can create a folder structure to let users upload their component projects.
You need a name or id to link this new uploaded project so you can load it later.
We want the plugins to be able to use the libraries our application is using (e.g. React, material-ui…)
If the use is only allowed to use the libraries you already have, you don't need to worry about their package.json.
In case you want to allow users to use their own libs, it adds some complexity on how to process this during runtime.
We need a way to "load" end-user code that is registering new widget types using our public API.
You can use create-react-app in this approach, but you may need a good definition of an entry point (in my example project, I'm using Index.js as the file I'll use as the main component of the project), or some kind of descriptor(maybe extending package.json) so you can read from your application to understand how to load the component. I'd go with the first approach, convention over configuration is more simple, and you can expand from that with a descriptor later.
by ejecting you can customize anything you want but you've to configure and maintain it by yourself, I think going through CreateReactApp also a good idea based on your criteria. I hope this article may help you out.
Thank You!
MSS-

Packaging JavaScript based plug and play application

I am trying to build a plug and play web based application that I should be able to integrate with multiple other web applications (which are developed using AngalurJS\ ExtJS\ ReactJS etc). On click of a button, I should be able to launch a sliding menu. On this menu, I want to add Twitter like functionality. On the first half of the menu we will have a textbox (with features like autocomplete & hash tags). The second half with show a gird which will show already posted messages. The panel will be responsible to get and post data to server.
The challenge is, I want to add this functionality to multiple other web applications with minimum configuration\changes. The consuming web applications should be able use this plugin with ease. Certain challenges I see is bootstrap does not play well with ExtJs framework & I may face similar issues with other JavaScript frameworks.
Questions:
How can I package this application? It has a panel with third party plugins (for autocomplete & other features), CSS & JavaScript. I can use web pack or Browserify but I want to keep the solution clean & don't want to add unnecessary dependency.
The consumers should be able to consume the bundle\package with ease & just by adding some references (like my bundle, css file, jquery, bootstrap).
I think, I can get the desired result with a simple ReactJs app, which I can bundle using web pack. But this will introduce other dependency. I want to keep the web application lite and simple.
I can use web pack or Browserify but I want to keep the solution clean & don't want to add unnecessary dependency.
I don't understand the problem. Using webpack or browserfy will only add devDependencies. You won't ship it. You package won't depend on it.
You won't be able to avoid using a bundler if you want to bundle it.
The consumers should be able to consume the bundle\package with ease & just by adding some references (like my bundle, css file, jquery, bootstrap).
If you distribute it via npm (de facto standard in JS), they just regularly import the resources with the correct path (e.g. node_modules/package/styles.css).
In npm you could also declare your peerDependencies (you mention jquery, bootstrap).
1. How can I package this application?
You should minify all your HTML using a build tool like grunt or gulp
If you want to keep the count of different files low, you can merge all your CSS, HTML and maybe even Images (base64 encoded) into your module.js. Ideally you could end up with only delivering a single file.
2. The consumers should be able to consume the bundle\package with ease & just by adding some references.
In that case they just need to include the script, like:
<script src="app-module.js"></script>
If you are able to use EcmaScript 2015, you might consider to package your plug-and-play app into a ES6 Module. Define your module.js simply as:
export var myNumber = 333
export function myFunction() {
...
}
And on the site, which is consuming your app, you simply add a dependency using the import keyword:
import * as service from 'module'
console.log(service.myNumber) // 333
Read more about ES6 Modules.

Get React components from the server with ajax

Is there a standard way to get React components dynamically from the server in order to render them at the client from already rendered components on demand? In other words, an already rendered component would return the ajax-received component when it will be re-rendered from the render() method.
With RequireJS and I think Browserify (using an extra package), scripts could be requested asynchronously. Currently I use webpack to transpile ES6 with Babelify.
My use case is that I want to create some sort of wysiwyg editor, and in theory there will be a repository of react-widgets that I would like to run on demand in an iFrame.
Thanks
If you are using webpack already you could look into the require.ensure functionality.
See: https://webpack.github.io/docs/code-splitting.html
This creates split points in your code without you having to do all the heavy lifting footwork.
I have a similar use case to yours and was able to use require.ensure successfully.
There are a few other tutorials/resources available:
http://jonathancreamer.com/advanced-webpack-part-2-code-splitting/
http://henleyedition.com/implicit-code-splitting-with-react-router-and-webpack/
https://www.youtube.com/watch?v=gvG8dSPCNno
Also, if you are building a wyisiwig editor you should check out draft-js.
https://facebook.github.io/draft-js/
Super cool and extensible, built right on top of React by the Facebook team.

How to dynamically load & render react components?

I need to be able to dynamically include react components into my project, because I want to setup a plugin system and not every user has the same plugins/components enabled. Also they are/might get too big to submit all of them to every user. I tried to find out how to do that, but it seems that React might not support that use-case.
TLDR: How do I load React components from server when needed? Do I have to switch to Angular because react has no templateUrl equivalent?
React components are defined in JavaScript files, so you can load components in just as you’d load in any other JavaScript file. If you’re not using any sort of module mechanism like RequireJS, that might be as simple as injecting a script tag into the document. If you’re using something like RequireJS, you would just tell the loader that you want an extra module loaded.

Categories

Resources