How to exclude library files from browserify bundle - node.js

I want to avoid cluttering up my distribution bundle with library files and use separate script tags for them in the HTML.
One way is like this...
m1.js
module.exports = "first module";
m2.js
module.exports = "second module";
cnd-m1.js
var m1 = "first module";
main.js
var m1 = this.m1 || require("./src/m1");
var m2 = require("./src/m2");
console.log(m1);
console.log(m2);
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>browserify test</title>
</head>
<body>
<script type="text/javascript" src="src/cdn-m1.js"></script>
<script type="text/javascript" src="dist/bundle.js"></script>
</body>
</html>
Where cdn-m1.js could be a library for example.
The only way I could figure out to make it work is to put a short-circuit fallback in the require statement and --ignore the file in my build.
in package.json
"scripts": {
"build-ignore": "browserify ./main.js -i ./src/m1.js > ./dist/bundle.js",
"build": "browserify ./main.js > ./dist/bundle.js"
},
Using the build-ignore script, the m1 module was stubbed in the bundle making it much smaller (assuming its a 50k line library) and it falls back on the cdn-served version.
bundle.js
function e(t, n, r) {
function s(o, u) {
if(!n[o]) {
if(!t[o]) {
var a = typeof require == "function" && require;
if(!u && a)return a(o, !0);
if(i)return i(o, !0);
var f = new Error("Cannot find module '" + o + "'");
throw f.code = "MODULE_NOT_FOUND", f
}
var l = n[o] = {exports: {}};
t[o][0].call(l.exports, function(e) {
var n = t[o][1][e];
return s(n ? n : e)
}, l, l.exports, e, t, n, r)
}
return n[o].exports
}
var i = typeof require == "function" && require;
for(var o = 0; o < r.length; o++)s(r[o]);
return s
})({
1: [function(require, module, exports) {
// browserify creates a stub for "./src/m1"
}, {}],
2: [function(require, module, exports) {
var m1 = this.m1 || require("./src/m1");
var m2 = require("./src/m2");
console.log(m1);
console.log(m2);
}, {"./src/m1": 1, "./src/m2": 3}],
3: [function(require, module, exports) {
module.exports = "second module";
}, {}]
}, {}, [2]);
Is there a better way to achieve this?

The answer is to use browserify-shim
In order to figure it out, I created a slightly more complicated scenario with a fake lib file (main-a.js) with two sub-dependencies (m1.js and m2.js) and made the app (main-b.js) dependent on the fake lib.
I rolled main-a.js into a stand-alone bundle that exposed one global called fakeLib and used a separate script tag in the index.html to load that.
I then used browserify-shim to build an isomorphic version of the app that required main-a.js in node, but used window.fakeLib in the browser.
using this app:
/**
* main-b.js
*/
require("./src/main-a").say();
This does not work:
"browserify-shim": {
"./src/main-a": "fakeLib"
},
but this does:
"browserify-shim": {
"./src/main-a": "global:fakeLib"
},
You must use this global:
I think that may be due to a bug in browserify because it doesn't agree with the browserify handbook
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>browserify test</title>
</head>
<body>
<div style="white-space: pre;" id="output"></div>
<script type="text/javascript" src="dist/main-a-lib-pretty.js"></script>
<script type="text/javascript" src="dist/bundle-B.js"></script>
</body>
</html>
Fake library...
/**
* m1.js
*/
exports.say = "first module";
.
/**
* m2.js
*/
exports.say = "second module";
.
/**
* main-a.js
*/
var m1 = require("./src/m1");
var m2 = require("./src/m2");
exports.say = function() {
function op(t){
this.document
? document.getElementById("output").textContent += t + "\n"
: console.log(t);
}
op(m1.say);
op(m2.say);
};
package.json for fake lib. This makes a standalone package that exposes fakeLib
{
"name": "browserify-nightmare",
"version": "1.0.0",
"main": "main-a.js",
"dependencies": {
},
"devDependencies": {
"browserify-shim": "^3.8.12"
},
"scripts": {
"build-lib": "browserify ./main-a.js -s fakeLib > ../dist/main-a-lib-pretty.js",
"build-lib-pretty": "browserify ./main-a.js -s fakeLib | js-beautify > ../dist/main-a-lib-pretty.js"
},
"author": "cool.blue",
"license": "MIT",
"description": ""
}
Fake app
/**
* main-b.js
*/
require("./src/main-a").say();
package.json that uses browserify-shim to return fakeLib from require("./src/main-a") in the browser but acts like a normal CommonJS module in node.
{
"name": "browserify-nightmare",
"version": "1.0.0",
"main": "main-b.js",
"browserify-shim": {
"./src/main-a": "global:fakeLib"
},
"browserify": {
"transform": "browserify-shim"
},
"devDependencies": {
"browserify-shim": "^3.8.12"
},
"scripts": {
"build-B": "browserify ./main-b.js > ./dist/bundle-B.js",
"build-B-pretty": "browserify ./main-b.js | js-beautify > ./dist/bundle-B.js"
},
"author": "cool.blue",
"license": "MIT",
"description": ""
}
this answer was super-helpful
git repo

First you have to create a seperate bundle for m1.js:
browserify -r ./src/m1.js > ./dist/m1_bundle.js
then simply create the "normal" bundle and reference to the created m1_bundle.js:
browserify -x m1 -d ./main.js > ./dist/bundle.js
now you have to include the two bundles into your HTML-file.
NOTE: you have to include the m1_bundle.js before the "normal" bundle.js in your HTML.
For more details show my other answer. There i explain, how to do the same thing but with node_modules instead of an own library.

Related

.glb file doesn't show in express server

I want to run a simple webserver that shows a .glb file in VR using a-frame.
When I use the "Open in Default Browser" extension in vs code the html below shows without problems, both box and file.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Hello, WebVR! • A-Frame</title>
<meta name="description" content="Hello, WebVR! • A-Frame">
<script src="https://aframe.io/releases/1.3.0/aframe.min.js"></script>
</head>
<body>
<a-scene background="color: #ECECEC">
<a-gltf-model position="4 -10 -100" rotation="210 0 0" src="/EPE_4.glb" shadow="receive: true"></a-gltf-model>
<a-box position="-1 0.5 -3" rotation="0 45 0" color="#4CC3D9" shadow></a-box>
<a-plane position="0 0 -4" rotation="-90 0 0" width="4" height="4" color="#7BC8A4" shadow></a-plane>
</a-scene>
</body>
</html>
However, when I run a server providing the html using Express, with the node command, only the box and plane is visible. Note that the .glb is somewhat large at 200 MB.
Below is my app.js and package.js file.
Thank you in advance for any help.
app.js
const app = express();
const path = require('path');
const router = express.Router();
router.get('/',function(req,res){
res.sendFile(path.join(__dirname+'/index.html'));
});
app.use('/', router);
app.listen(process.env.port || 3000);
console.log('Running at Port 3000');
package.js
{
"name": "vr_test2",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "node ./bin/www",
"devstart": "SET DEBUG=vr_test:* & nodemon ./bin/www"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"express": "^4.17.1"
}
}
If someone has a similar problem.
Check the browser's console log, mine showed that the webpage couldn't find the .glb file.
I solved this by adding a public folder and serving it to the client by using:
app.use(express.static('public'))

Using Mocked Service Worker (msw) with #web/test-runner

I am trying to setup msw with #web/test-runner (and playwright). The problem is that I don't know how the mockServiceWorker.js can be picked up by the test runner (which uses browser, not nodejs like jest). There is an example with karma:
https://github.com/mswjs/examples/tree/master/examples/with-karma, probably I have to do something similar but I have no idea where to start. Any hints are welcome.
I am not sure if it is important, but let me share my web.test-runner.config.js
import vite from 'vite-web-test-runner-plugin'
import { playwrightLauncher } from '#web/test-runner-playwright';
export default {
plugins: [ vite() ],
coverageConfig: {
include: [ 'src/**/*.{svelte,js,jsx,ts,tsx}' ]
},
browsers: [
playwrightLauncher({ product: 'chromium' })
],
testRunnerHtml: testFramework => `
<!DOCTYPE html>
<html>
<head>
<script type="module">
window.global = window;
window.process = { env: {} };
</script>
<script type="module" src="${testFramework}"></script>
</head>
</html>
};
and my test command
"test": "web-test-runner \"test/**/*.test.ts\"",

importScripts while error thrown from one of the script

In my chrome extension (manifest V3) I want to import some scripts like jquery and more.
Inside my backgound.js I have:
try {
importScripts('/js/jquery-3.4.1.min.js', '/js/common.js');
} catch (e) {
console.error('importScripts: ' + e);
}
...
calling to getCookie...
inside common.js I have function like:
async function getCookie(key) {
return ...;
}
but when I load the extension I get the error:
background.js:22 importScripts: TypeError: Cannot read property 'createElement' of undefined
This error comes from the Jquery library
and after I get another error:
Uncaught (in promise) ReferenceError: getCookie is not defined
because the error in jquery it doesn't load the common script? how can I fix that?
Is there a more stable solution to import the scripts? so that error in one script will not cause a fail to other scripts?
Posting the working solution for me: import the scripts from npm into background service worker:
In my manifest.json adding "type": "module" to my background script:
"background": {"service_worker": "background.js" , "type":"module"}
Inside my background.js simply importing desired module script:
import Dexie from "/node_modules/dexie/dist/modern/dexie.min.mjs"
REMAKRS:
Please notice that from Manifest Version 3 in order to invoke script into web-page from your background service workers you need to use chrome.scripting.executeScript. Example:
//background.js
let [tab] = await chrome.tabs.query({active: true, currentWindow: true})
//invoke function
await chrome.scripting.executeScript({
target: {tabId: tab.id},
function: colorSelectedText,
args: [tab.title]
})
});
//OR
//invoke file
await chrome.scripting.executeScript({
target: {tabId: tab.id},
files: ['your_script.js']
})
});
Desirable scripts must be in same parent folder as your manifest.json (wasn't working when I was trying to use two dots ../path)
You can package your extension application with the version of jquery you would like to use . then you add it as part of your service workers. This is how my manifest.json looks like
{
"name": "Foo Bar",
"description": "NA",
"version": "1.0",
"manifest_version": 3,
"permissions": [
"storage"
],
"action": {
"default_popup": "popup.html"
},
"background": { "service_workers": ["bg-loader.js","/js/jquery-3.6.0.min.js" ]}
}
I have a bg-loader.js which i use to import my js logic script where i have my jquery functions
try {
importScripts('/js/index.js' /*, and so on */);
} catch (e) {
console.error(e);
}
Then in my index.html i add my jquery script to my popup.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>test</title>
<link rel="stylesheet" href="css/styles.css">
</head>
<body>
</body>
<script type="text/javascript" src="js/jquery-3.6.0.min.js"></script>
<script type="text/javascript" src="js/index.js"></script>
</html>

Process is not defined for Electron's Getting Started App [duplicate]

This question already has answers here:
Unable to use Node.js APIs in renderer process
(2 answers)
Closed 1 year ago.
I am trying to get started with Electron. I was already able to run all simple examples. They all work as expected. When I try to follow the Quick Start Guide I experience the same issue as mentioned in this question: The app launches properly, but does not display the versions of node Chrome and Electron. When I look into the developing tools I see this error:
Uncaught ReferenceError: process is not defined
at index.html:14
However, I have set nodeIntegration to true.
Why is it still not working?
Versions:
npm 7.6.3
node v14.16.0
chromium 89.0.4389.82
Operating System:
Ubuntu 20.04.2 LTS.
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
</head>
<body style="background: white;">
<h1>Hello World!</h1>
<p>
We are using node
<script>document.write(process.versions.node)</script>,
Chrome
<script>document.write(process.versions.chrome)</script>,
and Electron
<script>document.write(process.versions.electron)</script>.
</p>
</body>
</html>
main.js
const { app, BrowserWindow } = require('electron')
function createWindow () {
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true
}
})
win.loadFile('index.html')
}
app.whenReady().then(createWindow)
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})
package.json
{
"name": "my-electron-app",
"version": "0.1.0",
"author": "username",
"description": "My Electron app",
"main": "main.js",
"scripts": {
"start": "electron ."
},
"devDependencies": {
"electron": "^12.0.0"
}
}
Try to set this value when creating your BrowserWindow:
webPreferences: { nodeIntegration: true, contextIsolation: false }
A new major Electron version has been released which broke the tutorial.
The specific breaking change is a new default value of contextIsolation flag.
For more details, see this GitHub issue.

Using Benchmarkjs with Webpack and Babel

I'm trying to get some basic benchmark tests working and am having trouble figuring out the right configuration. I'm trying to use Benchmarkjs with webpack and babel to transpile my code to es5. I created a benchmarks.webpack.js as an entry point which looks like this:
var context = require.context('./src/js', true, /-benchmark\.js$/);
context.keys().forEach(context);
module.exports = context;
I then have a benchmark file that I want to run (test-benchmark.js):
import benchmark from 'benchmark';
import benchmarks from 'beautify-benchmark';
let suite = new benchmark.Suite;
suite.add('RegExp#test', function() {
/o/.test('Hello World!');
})
.add('String#indexOf', function() {
'Hello World!'.indexOf('o') > -1;
})
.on('cycle', function(event) {
benchmarks.add(event.target);
})
.on('complete', function() {
benchmarks.log();
})
.run();
I updated my webpack build to try and transpile the benchmarks:
_.assign(config, {
devtool: 'eval-cheap-module-source-map',
output: {
path: path.join(__dirname, 'build/benchmark'),
filename: 'benchmark.js',
publicPath: '/'
},
entry: [
'./benchmarks.webpack.js'
],
plugins: [
],
module: {
loaders: [
{
test: /\.js$/,
loaders: ['babel?stage=0'],
include: path.join(__dirname, 'src/js')
},
]
},
});
Finally, I want to be able run this from an npm script:
"scripts": {
"bench": "webpack --config webpack.bench.config.js && node build/benchmark/benchmark.js"
},
However, I'm getting warnings that the result of the benchmark dependency is an expression and there no suitable loaders for the .json, .txt, etc files. I tried hacking up Benchmarkjs to export correctly but was not successful.
WARNING in ./~/benchmark/benchmark.js
Critical dependencies:
1122:34-49 the request of a dependency is an expression
# ./~/benchmark/benchmark.js 1122:34-49
WARNING in ./~/benchmark/package.json
Module parse failed: /home/bill/dev/levelstory/react-client-redux/node_modules/benchmark/package.json Line 2: Unexpected token :
You may need an appropriate loader to handle this file type.
| {
| "name": "benchmark",
| "version": "1.0.0",
| "description": "A benchmarking library that works on nearly all JavaScript platforms, supports high-resolution timers, and returns statistically significant results.",
# ./~/benchmark ^\.\/.*$
WARNING in ./~/benchmark/LICENSE.txt
Module parse failed: /home/bill/dev/levelstory/react-client-redux/node_modules/benchmark/LICENSE.txt Line 1: Unexpected number
You may need an appropriate loader to handle this file type.
| Copyright 2010-2012 Mathias Bynens <http://mathiasbynens.be/>
| Based on JSLitmus.js, copyright Robert Kieffer <http://broofa.com/>
| Modified by John-David Dalton <http://allyoucanleet.com/>
# ./~/benchmark ^\.\/.*$
Looks like benchmark does something special with require. That messes it up for Webpack. It has the following lines:
var freeRequire = typeof require == 'function' && require;
...
function req(id) {
try {
var result = freeExports && freeRequire(id);
} catch(e) { }
return result || null;
}
If you comment out the function contents, the error goes away. Given it's not ideal to patch around it this way I would poke the benchmark guys about this directly instead. Perhaps there's something we're missing.

Resources