How to create and publish a vue global function to NPM? - javascript

I know it sounds a bit confusing, but let me explain it here:
Right now there's a module that can be imported as CDN only:
<script src='https://www.example.com/example.min.js'></script>
after including it in index.html (or any .html file)
There's a few functions that can use from the module
<script>
$example_function.doSomething(param1,param2);
$example_function.doSomething2();
</script>
Because the module does not available as NPM package and for people like me want to use it in webpack built Vue.js project it's not so straight forward to use this module.
I know there's plenty of ways to workaround but I want it to be simple as I can just import it globally like other npm packages
import Example from 'example'
Vue.use(Example)
then I can call the function in any Vue components, or in my future vue projects.
Is it possible to achieve this?

Related

Where do external dependencies live in vanilla JS web components?

I'm experimenting with using web components for a project — essentially custom elements powered by attributes, ideally imported by <link rel="import">.
Here's the problem: I can't find conclusive guidance on where to stick any external libraries my component relies on, such as moment.js or even jQuery.
Most component examples I've seen strictly use vanilla JS. When they do use an external library, they often seem to drop them in using Bower or npm and and refer to them explicitly within the component's HTML:
<script type="text/javascript"
src="/bower_components/jquery/dist/jquery.min.js></script>
These days I'm more accustomed to using webpack to bundle dependencies, so this seems a bit odd.
My question: is it considered better form to include each component's library dependencies within the component directory, or have a central node_modules folder at the project level? How does webpack fit into this?
It's better to have a central node_modules folder at the project level. Most people use Webpack to bundle their code with their dependencies. They use require or import their modules for each component.
a.component.js
import React from 'react'
import $ from 'jquery'
b.component.js
import React from 'react'
app.js
import A from 'a.component.js'
import B from 'b.component.js'
Webpack will have one "entry": app.js and compile it output: app.min.js
why?
It's easier to manage (update, delete, add) dependencies with npm.
The browser will load one file instead of multiple external files.
External info:
https://webpack.js.org/concepts/
https://www.quora.com/Why-use-Bower-when-there-is-npm

How to include 3rd party library that uses older import approach to Angular4.x?

What is the proper workflow to include the library to angular 4.0 and use it inside a component?
My steps:
yarn add mathjs
Then there should be a way to injects js libraries in one of the build lifecycles so the angular4 component can use it. JHipster utilizes Webpack and Yarn.
Then I tried to add to Component (docs):
import { mathjs } from "./mathjs";
and
var math = require('mathjs');
Those were not working. What am I missing?
UPDATE:
It seems like mathjs uses older approach suggesting var math = require('mathjs'). Maybe it is similar to JQuery question in some way...
UPDATE2
This is a great question and I'm glad you ask because I wish I had what I'm about to write the first time I encountered this little problem. This is a typescript/javascript and webpack issue before it is an angular issue. I definitely am planning a writeup on my blog soon as possible.
Your Scenario:
You run
npm install mathjs
Now you try to use math.js from a component:
Find math.js dist js file (node_modules/mathjs/dist/math.js) and reference like this
import {mathjs} from "../../node_modules/mathjs/dist/math";
But you get error message saying "set --allowJS". You do that like this:
Set --allowJS in config (tsconfig.json)
{ "compilerOptions": {
"allowJs": true, ...
Now you get:
ERROR in ../node_modules/mathjs/dist/math.js (12209,13): Unreachable
code detected.
Looking in the math.js source, you see that it is an old school module but there is no root wrapper function (one function to bring them all and in the darkness bind them..) (more on that later).
Solution: install a typings file for the target lib (#types/mathjs)
First, check to see if you can get #typings files for your module here
https://microsoft.github.io/TypeSearch/
Grab mathjs typings file from npm (https://www.npmjs.com/package/#types/mathjs) and Run npm install to add the typings .d.ts files to the target lib's node_modules directory
npm install --save #types/mathjs
Add your type ref correctly
import * as mjs from "mathjs"
Use it like this:
console.log("e was: " + mjs.e);
I have the complete solution for the math.js lib on my github here
https://github.com/res63661/importOldJSDemoWithTypings/
More:
For examples look no further than your own angular project. CLI creates node_modules folder each time you run npm install after creating a new project with ng new . Dig down into here and note the d.ts files for many of the .js files.
When messing with typings or defining your own (.d.ts files) be sure to restart your server between builds as the typings don't seem to update currently on the fly
Further reading:
http://www.typescriptlang.org/docs/handbook/declaration-files/consumption.html
https://angular.io/guide/typescript-configuration#typescript-typings
https://microsoft.github.io/TypeSearch/
Lastly:
If you are in a pinch and this is not working for you, I did have success creating a custom wrapper for a different (much smaller) module by wrapping it in a master export type
export var moduleNamer = (function(){
//module implementation
}());
then dumping the .js file local to my component and then referencing it as follows:
//reference like this from your component:
import {moduleNamer} from "./source"; //from source.js
--rich
I did this way and it worked for angular9.
First install npm package mathjs.
npm install mathjs
Then import in your component or directive.
import { round } from 'mathjs'
You may test with this.
console.log(round(math.pi, 3) )
Try to include the script into index.html:
<script src="./assets/math.js" type="text/javascript"></script>
Then add this into your component file:
declare const math;
You can then use math in your component:
ngOnInit(): void {
console.log(math.sqrt(-4););
}

How can I import gl-matrix in a ReactJS project?

I have just tried using ReactJS recently, and I came across and played with this project which import JS modules via syntax like this:
import Particle from './Particle'
I wished to port the project to use gl-matrix as a practice to get familiar myself with this framework, but now I'm unsure how I should proceed. Should I be able to require as suggested on this page, or there is some way to import gl-matrix?
I believe you can just require it like usual:
var glm = require('gl-matrix');
Of course, make sure you've run
npm install --save gl-matrix
or have gl-matrix as a dependency in your package.json. If that doesn't work, try just importing the script directly in your index.html:
<script src="gl-matrix-min.js"></script>
Then you should be good.

ES6 module import and dependency management

With the use of transpilers it is already possible to use ES6 modules. One of the easiest ways is using Browserify and Babelify.
The problem I'm having is how to handle dependency management.
In the old days you'd just have some Bower dependencies. The build would bundle non-CDN to vendor.js and project specific files to foobar.js (or whatever).
So then you'd be able to use the resulting code in a different project by simply bower install foobar --save.
If both foobar and your new project had a common dependency it would be easily resolved with Bowers flat dependency.
Now in come ES6 modules:
Say I have a project foo using lodash. The directory structure is as follows:
src/js/foo.js
src/vendor/lodash/dist/lodash.min.js
And foo.js starts by declaring:
import * as _ from '../../vendor/lodash/dist/lodash.min.js';
or (as Browserify wants since Babelify transpiles to CommonJS):
import * as _ from './../../vendor/lodash/dist/lodash.min.js';
If I now round up and publish my foo project and start a new project bar that uses foo this will be my directory structure.
src/js/bar.js
src/vendor/foo/dist/foo.js
src/vendor/lodash/dist/lodash.min.js
But that would not work since the path from foo to lodash is now broken (if I understand Browserify correctly the dot-slash in './blaat/file.js' is relative to the file it's being called from).
Is some way to import without making any file path assumptions?
Isn't there some way to indicate multiple source roots? (ie in the above case src/js and src/vendor ... well, ideally you'd just want to state import * as _ from 'lodash';)
I've only used Browserify with Babelify on cli. Should I be using some other transpiler?
I think that jspm is the solution your looking for. It will help you out without making file path assumptions when importing modules. It uses the SystemJS dynamic ES6 loader. Watch the video that is posted on their site for a very good explanation on how it all works, Guy Bedford: Package Management for ES6 Modules [JSConf2014].

Browserify including entire module when only some parts used (react-addons)

I'm using Browserify to bundle serverside react.js code for the client.
However, I have a bad feeling that using a module from within an npm package results in that entire package being bundled by Browserify.
Q: Does require('react-addons').LinkedStateMixin result in the entire react-addons package being bundled into my Browserified JS?
IE: does Browserify treat require('react-addons').LinkedStateMixin the same as require('react-addons')?
If so, is there any way around this? External tools, Browserify options etc.
Browserify does not have the ability to extract parts of the functionality from a module.
What you can do though, is require the desired module from within react-addons like this:
require('react-addons/lib/LinkedStateMixin')
This will only include the one module (and it's dependencies) in your bundle. However, you now depend on the internal structure of the module. If the LinkedStateMixin is renamed, you will have to change your require statement.
#mantoni was helpful but as this is a react-addons specific question i will post my answer.
Don't use react-addons and react side by side. Instead, when requiring React use require('react/addons'). This calls a script at /addons/ that returns the full React with addons.
So for my example:
var React = require('react/addons');
var LinkedStateMixin = React.LinkedStateMixin;
//this works as normal!
React.createClass({});
Thanks guys!
In ReactJS 0.13.3 if you want to use e.g. CSSTransitionGroup you have to do the next:
var React = require('react/addons'),
CSSTransitionGroup = React.addons.CSSTransitionGroup;
And all that has to be installed – npm install react.

Categories

Resources