Embed Emscripten WebAssembly module in npm package - npm

I'm building an npm package that contains some WebAssembly loaded from Emscripten module "glue code".
For now, the WASM is fetched from the glue code via a static specified URL
// emscripten glue code
import rppgLoader from './set_asm.js';
async load() {
// load webassembly code
this.instance = rppgLoader({
locateFile(path) {
return `${process.env.PUBLIC_URL}/wasm/set_asm.wasm`;
}
});
This URL is application-specific and therefore not compatible with an npm module where everything has to be included and compatible with most build systems (webpack, browserify, ...)
I tried following a gist by google engineer #surma that aims at making wasm/emscripten and webpack work together but got no luck (see last comment on the gist)
What I'm trying to achieve is a npm module transparent for the user. E.g this:
npm install x
import { y } from "x";
should work. That include the wasm code and is compatible with most bundlers.
Is this possible? And if so, is there any examples of npm package that made it work ?
Cheers!

I bundled a WASM module into the opus-stream-decoder NPM package. package.json uses the main property to declare the WASM entry point. Also have a look at the test-* files that show import it, using the new ES Modules import syntax or the older require()

Related

Use vue-cli-service to build a library, how to transpile?

I'm trying to build a library (mostly some .vue components) to reuse in different projects (no public npm) with vue-cli-service. Apparently everything its already setup, and I can confirm that the build is fine (js, and css). However, I'm unable to use it in a separate project as an external module because it uses the spread operator (and probably more ES20XX features no yet parsed).
Module parse failed: Unexpected token (2683:8)
You may need an appropriate loader to handle this file type.
| params() {
| const queryParams = {
| ...this.filters,
| ...this.sorting,
| ...this.config.params,
This is the standard command I'm using to build the library
vue-cli-service build --target lib --name [mylibname] ./src/components/index.js
By default the bundle should be already polyfilled but it seems to me that it's not the case.
I've read that I might change the webpack configuration on the project I'm using into, but I'm against parsing the whole node_module folder and also I would love to just have the simplest workflow possible (like import a module and its css).
So my question is, how to polyfill my bundle to be perfectly usable in no matter what Vue project without any hassle ?
Ok, it seems that reinitializing the project with vue-cli without typescript and with separated configuration files instead of into package.json was a good idea, as now is transpiled as needed.
var queryParams = _objectSpread({}, this.filters, {}, this.sorting, {}, this.config.params);
Unfortunately the hidden configuration of vue-cli webpack can't help to see what has changed.

#vue/cli application build fail using my library

I'm writing a Vue component library let's call it my-component,
when I download it from npm or use npm link to test in vue/cli application,
import { component } from `my-component`
It will fail on IE... but fine with chrome
But if I put my library's source code under my application folder,
import { component } from './lib/my-component/entry.js'
everything goes well.
Why webpack/vue-cli build differently in two ways?
Did I need extra settings to publish my component as a library?

How to publish a vue js plugin that modifies an existing plugin

I am trying to create a plugin that utilizes components from another Vuejs plugin (Vuetify). Basically, I have some common components I want to share across multiple applications with our company.
I thought it would just be a matter of:
Create a github repo for the shared components
Author the plugin
Reference the repo in consuming apps via npm install
Here is the gist of the plugin:
// src/index.js <-- package.json/main is set to "src"
import MyComponent from "./MyComponent.vue";
import * as api from "./api";
export default function install(Vue) {
Vue.component("myComponent", MyComponent );
Vue.prototype.$myApi = api;
}
At the moment, the behavior I'm seeing is:
GOOD
plugin install function is being executed
functions from api attached to Vue.prototype are available in app components
my-component is available in the app and renders markup
BAD
$myApi and Vuetify components are not available in an application instance of of my-component
If I copy the same files into the app and change my import, all works as expected. So, I now wonder if I'm missing something regarding sharing code via external modules.
I've tried these alternatives with the same issue:
use npm link to link the plugin module to the app
manually, use mklink (Windows sym link) to link plugin module to node_modules in the app folder
use a long relative path reference to the plugin module: import MyPlugin from "../../../my-plugin"
I've put this issue off for a while, but for anyone wondering, the issue is with using Single File Components and webpack not compiling those in external modules.
The 2 options I have are:
Don't use Single File Components. I.e.: Just use .js instead of .vue. I've seen some libs like Vuetify.js take this approach
Compile the .vue files in the library module and include them in the source such as ./dist folder.

How to import bower components to an npm, webpack project?

I have set up a basic webpack/babel/mocha project just for playing around. Now I installed jQuery and Paper.js to my project with Bower, but I want them to be bundled with webpack on npm start, I don't want to write extra <script> tags etc.
I just want to use them as import $ jQuery from 'jquery'. But now my setup looks for the jquery package in npm_modules. How can I tell npm to look for these in the bower_components folder?
Is this a logical decision tho? Or am I supposed to set up this any other way?
Personally, I'd usually recommend installing everything through NPM - most frontend dependencies are on there these days. However, it does say on the Paper.js NPM page that they recommend using Bower to download the browser version of the library (perhaps there's some Node-specific code in the NPM package? I'm not sure).
To get Webpack working with Bower packages, you can set a custom name/path using config.resolve.alias:
var path = require("path");
var config = {
...
resolve: {
alias: {
"jquery": path.resolve(__dirname, "path/to/bower/file"),
"paper": path.resolve(__dirname, "path/to/bower/file")
}
}
...
}
This can come in handy in quite a few situations outside of Bower, too - for example, if you need to use a library that isn't currently distributed through a package manager, you can just add it to your project folder and use an alias to make it available to your code.

How to use browserify with non-npm libraries?

According to http://www.slant.co/topics/1089/viewpoints/1/~what-are-the-best-client-side-javascript-module-loaders~browserify#9 one of the downside of using Browserify is that:
Not all javascript libraries have an npm version
While it's not too hard to create npm package for an existing library, it means maintaining it when the library updates. While most libraries are now on npm, many client side specific libraries are not.
I don't have any experience with npm aside from knowing how to install an existing module. In light of that, what is the easiest/best way to browserify with client-side non-npm libraries?
Is there a way for me to declare a local Javascript file as a dependency, instead of looking it up through npm?
You can use local modules without problems by two ways:
1.Use a relative path to a module in require:
var myModule = require('../js/my-module');
2.Use a module name, but before, you should to add it to browser property in package.json:
package.json:
...
browser: {
my-module: './js/my-module.js'
}
app.js:
var myModule = require('my-module');
Some packages are packages with bower, these can be used with browserify by using the debowerify plugin.
For non-versioned things you can copy them to a lib directory in your project or add them as a git submodule and then configure browserify so that it can find things there too.