How to browserify a standalone module for use in WebWorkers - node.js

I am using browserify to create standalone modules that I can use in node.js and client side in browser. I don't use browserify on the entire app, just a few single node modules.
I do browserify-shim to shim e.g. lodash under the global var _.
This works very well except when using the modules inside webworkers.
The problem is:
When I shim lodash as _ the browserified code sets var _ = window._,
but windows is not defined inside the web workers.
My setup
I use grunt to browserify, and have browserify-shim configured in my package.json
map.js: (commonJS module, used directly in node.js)
var _ = require('lodash-node');
module.exports = _.map;
GruntFile.js:
// Browserify
grunt.loadNpmTasks('grunt-browserify');
grunt.initConfig({
browserify: {
'map': {
options: {
bundleOptions: {
standalone: 'MapModule'
}
},
src: ['./map.js'],
dest: './output/map-module.js'
}
}
});
grunt.registerTask('default', [
'browserify'
]);
package.json:(partial)
{
"name": "APP NAME",
"version": "0.0.0",
"description": "",
"main": "app.js",
"browserify": {
"transform": [
"browserify-shim"
]
},
"browserify-shim": {
"lodash-node": "global:_"
},
}
The output
the generated output from browserify looks like this:
https://gist.github.com/mikaelhm/859735472c9b0038770e
Note line 2: var _ = (window._);
Thats a problem in a Web Worker.
Am I doing it all wrong, or is it only supposed to work in normal browsing mode?

I know this is an old post but I'm sharing the solution I found as this took me a few hours to find a solution.
I managed to get web workers running as modules using
https://github.com/substack/webworkify it's avaliable as via npm install webworkify.
A task I had to perform inside my web worker was to parse an xml string to javascript this I did with xmldoc, as xmldoc does not require a DOM and there is no DOM in web workers.
I include xmldoc in my web worker with require, which would be the same for lodash.

Related

How I can use a commonjs module in my quasar project

I an SSR Quasar project using Vite. Whenever I try to add the #tiptap/extension-code-block-lowlight extension to my project, build it and then node dist/ssr/index.js it throws the following error:
Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: /home/whatever/devotto/devotto.com/node_modules/lowlight/lib/common.js
require() of ES modules is not supported.
require() of /home/whatever/devotto/devotto.com/node_modules/lowlight/lib/common.js from /home/whatever/devotto/devotto.com/dist/ssr/server/server-entry.js is an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which defines all .js files in that package scope as ES modules.
Instead rename common.js to end in .cjs, change the requiring code to use import(), or remove "type": "module" from /home/whatever/devotto/devotto.com/node_modules/lowlight/package.json.
Upon investigation, I have concluded that the issue is the lowlight library being imported by #tiptap/extension-code-block-lowlight.
If I manually go to my node_modules/#tiptap/extension-code-block-lowlight/package.json AND node_modules/lowlight/package.json and remove the line "type": "module", I can run the project with no problem (e.g. yarn build && node dist/ssr/index.js.
This solution works on my current machine but I shouldn't have to touch the node_modules folder.
I would assume that I have to transpile lowlight library which prompts me to try to alter Vite configuration but no luck there as well
module.exports = function() {
return {
build: {
extendViteConf (viteConf, { isClient, isServer }) {
if (isServer) {
viteConf.optimizeDeps = viteConf.optimizeDeps || {};
viteConf.optimizeDeps.include = ['./node_modules/highlight.js'];
viteConf.build.commonjsOptions = viteConf.build.commonjsOptions || {};
viteConf.build.commonjsOptions.include = [/highlight.js/, /node_modules/];
// viteConf.optimizeDeps.entries = [
// 'node_modules/#tiptap/extension-code-block-lowlight/dist/tiptap-extension-code-block-lowlight.cjs',
// 'node_modules/highlight.js'
// ];
}
},
}
}
}
Is there a solution to this issue without having to manually change node_module folder? Thank you very much in advance.
I didn't exactly solve the question. I only applied an automated way to handle this whenever I run the command to build the server using pre scripts.
On my package.json:
{
"scripts": {
"start:test:webserver": "ENV_FILE=test quasar build --mode ssr --port 3000 && node dist/ssr/index.js",
"prestart:test:webserver": "sed -i '/\"type\": \"module\",/d' node_modules/lowlight/package.json && sed -i '/\"type\": \"module\",/d' node_modules/#tiptap/extension-code-block-lowlight/package.json",
}
}

Must use import to load ES Module - lowlight with Quasar app [duplicate]

I an SSR Quasar project using Vite. Whenever I try to add the #tiptap/extension-code-block-lowlight extension to my project, build it and then node dist/ssr/index.js it throws the following error:
Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: /home/whatever/devotto/devotto.com/node_modules/lowlight/lib/common.js
require() of ES modules is not supported.
require() of /home/whatever/devotto/devotto.com/node_modules/lowlight/lib/common.js from /home/whatever/devotto/devotto.com/dist/ssr/server/server-entry.js is an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which defines all .js files in that package scope as ES modules.
Instead rename common.js to end in .cjs, change the requiring code to use import(), or remove "type": "module" from /home/whatever/devotto/devotto.com/node_modules/lowlight/package.json.
Upon investigation, I have concluded that the issue is the lowlight library being imported by #tiptap/extension-code-block-lowlight.
If I manually go to my node_modules/#tiptap/extension-code-block-lowlight/package.json AND node_modules/lowlight/package.json and remove the line "type": "module", I can run the project with no problem (e.g. yarn build && node dist/ssr/index.js.
This solution works on my current machine but I shouldn't have to touch the node_modules folder.
I would assume that I have to transpile lowlight library which prompts me to try to alter Vite configuration but no luck there as well
module.exports = function() {
return {
build: {
extendViteConf (viteConf, { isClient, isServer }) {
if (isServer) {
viteConf.optimizeDeps = viteConf.optimizeDeps || {};
viteConf.optimizeDeps.include = ['./node_modules/highlight.js'];
viteConf.build.commonjsOptions = viteConf.build.commonjsOptions || {};
viteConf.build.commonjsOptions.include = [/highlight.js/, /node_modules/];
// viteConf.optimizeDeps.entries = [
// 'node_modules/#tiptap/extension-code-block-lowlight/dist/tiptap-extension-code-block-lowlight.cjs',
// 'node_modules/highlight.js'
// ];
}
},
}
}
}
Is there a solution to this issue without having to manually change node_module folder? Thank you very much in advance.
I didn't exactly solve the question. I only applied an automated way to handle this whenever I run the command to build the server using pre scripts.
On my package.json:
{
"scripts": {
"start:test:webserver": "ENV_FILE=test quasar build --mode ssr --port 3000 && node dist/ssr/index.js",
"prestart:test:webserver": "sed -i '/\"type\": \"module\",/d' node_modules/lowlight/package.json && sed -i '/\"type\": \"module\",/d' node_modules/#tiptap/extension-code-block-lowlight/package.json",
}
}

Multiple NPM repos in one GitHub repo with scoping?

Let's say I have a client, awesome-service that composes of different types of services, http-service, log-service, etc...
I want to have the option of either including each individual service (and a specific version), or just require all of the awesome-services, so in effect I want something like:
const awesomeService = require('#awesome-service');
// Now awesomeService has
// awesomeService.httpService;
// awesomeService.logService;
// etc
// or individually
const httpService = require('#awesome-service/http-service');
Is this possible? What would the package.json and the GitHub organization look like? Maybe this is package.json?
"dependencies": {
"awesome-service": "#awesome-service"
// OR if individually importing them
"http-service": "#awesome-service/http-service#1.0.0"
}
How can this be accomplished, or rather can this be accomplished?
Is this possible?
Yes, it's possible.
What would the package.json and the GitHub organization look like?
The package should have the following structure:
- awesome-service
- index.js // main module
- package.json // package.json of the main package
- http-service
- index.js // implementation of `http` service
- package.json // package.json of `http` package
- log-service
- index.js // implementation of `log` service
- package.json // package.json of `log` package
As you see there are three package.json files. The root is used for main package, others for each service.
In each package.json, set main field to index.js and set a correct name for each package:
{
"name": "awesome-service",
"main": "index.js",
...
}
{
"name": "awesome-service#http-service",
"main": "index.js",
...
}
{
"name": "awesome-service#log-service",
"main": "index.js",
...
}
In index.js of the root package export the object with the fields - required services (I don't specify index.js in requires, because this module will be loaded by default):
module.exports = {
httpService: require('./http-service'),
logService: require('./log-service')
};
To use these three package separately, you should add all of them in npm, or use github with a proper url:
"dependencies": {
"awesome-service": "awesome-service"
"http-service": "awesome-service#http-service#1.0.0",
"log-service": "git+https://github.com/yourAccount/awesome-service/log-service.git"
}

Require dependency of dependency

I have the modules as shown above. I need to include not only quickblox, but the quickblox.chat plugin.
I'm using this code:
// Quickblox
var QB = require('quickblox');
var QBChat = require('quickblox/plugins/chat');
quickblox loads fine but quickblox/plugins/chat throws:
Error: Cannot find module 'quickblox/plugins/chat'
Here is the package.json included in the quickblox/plugins/chat directory:
{
"name": "quickblox.chat",
"description": "Quickblox Javascript SDK / XMPP Chat plugin",
"version": "0.8.6",
"author": "Andrey Povelichenko <andrey.povelichenko#quickblox.com>",
"homepage": "http://quickblox.com/developers/Web_XMPP_Chat_Sample"
}
If you call require with a folder path, it tries to load index.js, which doesn't exist.
var QBChat = require('quickblox/plugins/chat/quickblox.chat');

require cdn libraries in browserify without bundling it in the final js file

If I have a library that is being pulled down from cdn and wouldn't like it to be part of the final js file but be able to require it using browserify, how would I solve it?
Here is how I currently solve it using alias and a shim file.
browserify: {
options: {
debug: true,
transform: [ 'reactify' ],
alias: [
'client/shims/jquery.js:jquery'
]
},
app: {
src: 'client/app.js',
dest: 'public/app.js'
}
}
here is the shim file client/shims/jquery.js which I alias to jquery so I can use require('jquery') instead of the full path.
module.exports = $;
Is there a shortcut in grunt-browserify to support this scenario? I would like to know if it is possible to define it in Gruntfile.js without creating the shim file.
Adding external: [ 'jquery' ] seems to totally ignore it and doesn't work.
With browserify-shim you can add this in your package.json file:
"browserify": {
"transform": [
"browserify-shim"
]
},
"browserify-shim": {
"jquery": "global:$"
}
Then jquery will be available in your modules via require('jquery')
If you load jQuery before the Browserify bundle on the page, $ will be available as a global.

Resources