I have included (via npm) the twilio/voice-sdk package (v.2.1.0) into a project. When I include the following code (as shown in many examples):
const Device = require('#twilio/voice-sdk').Device;
I get a console error stating:
"Cannot find module 'events' in '#twilio/audioplayer/es5'". I am trying to import this onto the client side, not server.
I get this whether I use require or import.
As an attempt around this, I have also include the node package #twilio/audioplayer, but to no avail. Kind of stuck as to what is going on here.
I am trying to use this on a Wix (or Velo more specifically) project. Hoping to create a dialer that can both answer and instigate phone calls on a site that already exists on that platform.
I have installed both of the above npm packages into my project, but get he above enumerated error.
Any ideas from the Internet?
Additional Information:
If I add the 'require' on the server side I do not get the same error. I was going to try this and then do an async call to the server to get my Device object. However, the Twilio Device SDK package utilizes the Window object, which of course does not exist on the server side.
The #twilio/audioplayer package uses the "events" module. This module is available in Node.js and when applications are bundled with something like Webpack is polyfilled.
I haven't used Velo, but I assume they are bundling differently in a way that doesn't add polyfills for this. I'd recommend installing the events npm module to your project too. That should provide the EventEmitter that the library is using for the browser environment and stop this error.
I had a similar problem, where I can import Device, but cannot construct it. The problem I had was that the bundler (in my case Vite) doesn't have a polyfill to run some functions inside the #twilio/voice-sdk.
The solution in my case was by installing polyfill on Vite.
Here is how:
First, install these packages:
npm i #esbuild-plugins/node-globals-polyfill #esbuild-plugins/node-modules-polyfill --save-dev
Then add the polyfill config to your vite.config.js. Here is link of the code: https://medium.com/#ftaioli/using-node-js-builtin-modules-with-vite-6194737c2cd2.
Because I use React, I still need to add plugins: [react()] inside the polyfill config. So it becomes something like:
export default defineConfig({
plugins: [react()],
// rest of the polyfill config
})
Now you can do:
import { Device } from "#twilio/voice-sdk";
new Device(token);
Related
I'm building a simple Electron app for MacOS (using React as the frontend). The purpose of the app was to make executing certain terminal commands a lot easier (using child_process.spawn. Primarily I am interested in using the sfdx Salesforce CLI commands.
When I run the app in dev, everything works fine. However when I package the app, the PATH variable gets changed and I'm no longer able to locate the sfdx library. (*note it is still able to find git commands though).
I found a very similar issue here and a bug report in GitHub, both of which recommend the use of the fix-path package. This is where I run into another issue. According to the docs, I should import the package like this:
import fixPath from 'fix-path';
However when I do that inside of my electron.js file I get this error: SyntaxError: Cannot use import statement outside a module. I've seen other resources that use require to bring in the package:
const fixPath = require('fix-path');
But again, when I do that I get this error require() of ES Module not supported.
I tried adding "type": "module" to my package.json file, but that breaks my app as well.
I feel like there is something simple that I am missing here, but can't seem to figure out. I believe that if I could import and use the fix-path package, then this would solve my problems. But if that isn't possible, does anyone know of a way for me to fix the path in my app so that it works in prod?
Thank you in advance!
Some extra details:
The two dependencies I check for are git and sfdx. The following image shows where both of those live on my machine:
And this is the response to the same commands within the packages asar file:
I found a workaround, it looks like fix-path made a move to ESM during the last release. Because I am using CJS modules I just needed to install version 3 of fix-path by running npm install fix-path#3.0.0 --save
I tried so but I have a 'require is not defined' error. I can't find information about that, can someone enlighten the noob in me please?
It's possible, but you have to be careful. Trying to require() a package means that node will try to locate its files in your file system. A chrome extension only has access to the files you declare in the manifest, not your filesystem.
To get around this, use a module bundler like Webpack, which will generate a single javascript file containing all code for all packages included through require(). You will have to generate a separate module for each component of your chrome extension (e.g. one for the background page, one for content scripts, one for the popup) and declare each generated module in your manifest.
To avoid trying to setup your build system to make using require() possible, I suggest starting with a boilerplate project. You can check out my extension to see how I do it.
An updated answer for 2022
Short answer: yes, you can require/import packages. Rather than going through the tedious work of setting up & configuring a bundler like Webpack on your own (especially if you have no experience with them), there are now build tools you can use to create the boilerplate "scaffolding" for a Chrome extension:
Extension CLI -- this one is well-documented and you can also reference the source code of some Chrome extensions that have used this tool (READ: learn how others have set up their code).
Chrome Extension CLI
Benefits of using them:
New projects are initiated with a default project file structure. Super helpful.
They support modern Javascript (ES6, ES2021), so modules work fine.
They already have bundlers integrated and pre-configured (Webpack in both above cases I think). You therefore don't need to install and configure any on your own.
You can use npm as normal to install any packages/dependencies you need.
Then of course, let the official documentation for Chrome Extensions guide you through the rest.
It's not possible to require node modules directly within a chrome extension. However, it is possible to bundle node applications and packages into the browser for use with your extensions. See here for more: Is it possible to develop Google Chrome extensions using node.js?
Yes, It is possible with esm npm packages.
require is commonjs module loader.
Browser doesn't support commonjs modules system
so that this error showed.
Method 1:
Run npm init -y and add "type" :"module" in your package.json.
create path.js file
add this line in path.js
const fullPath = await import.meta.resolve("npm-pkg-name");
const path = fullPath?.match(/(/node_modules.*)/)[0];
console.log(path);
add this line inside package.json
"path": "node --experimental-import-meta-resolve path.js",
Copy console output text. Replace package name with this copied path.
Method 2:
Install other npm package to find and replace
npm packages' virtual path to real path so that chrome browser will find it.
Install Path-fixxer
Add this line in path.js
import setAllPkgPath from "path-fixxer";
setAllPkgPath();
then run command : npm run path.
Now open browser to test it.
I tried so but I have a 'require is not defined' error. I can't find information about that, can someone enlighten the noob in me please?
It's possible, but you have to be careful. Trying to require() a package means that node will try to locate its files in your file system. A chrome extension only has access to the files you declare in the manifest, not your filesystem.
To get around this, use a module bundler like Webpack, which will generate a single javascript file containing all code for all packages included through require(). You will have to generate a separate module for each component of your chrome extension (e.g. one for the background page, one for content scripts, one for the popup) and declare each generated module in your manifest.
To avoid trying to setup your build system to make using require() possible, I suggest starting with a boilerplate project. You can check out my extension to see how I do it.
An updated answer for 2022
Short answer: yes, you can require/import packages. Rather than going through the tedious work of setting up & configuring a bundler like Webpack on your own (especially if you have no experience with them), there are now build tools you can use to create the boilerplate "scaffolding" for a Chrome extension:
Extension CLI -- this one is well-documented and you can also reference the source code of some Chrome extensions that have used this tool (READ: learn how others have set up their code).
Chrome Extension CLI
Benefits of using them:
New projects are initiated with a default project file structure. Super helpful.
They support modern Javascript (ES6, ES2021), so modules work fine.
They already have bundlers integrated and pre-configured (Webpack in both above cases I think). You therefore don't need to install and configure any on your own.
You can use npm as normal to install any packages/dependencies you need.
Then of course, let the official documentation for Chrome Extensions guide you through the rest.
It's not possible to require node modules directly within a chrome extension. However, it is possible to bundle node applications and packages into the browser for use with your extensions. See here for more: Is it possible to develop Google Chrome extensions using node.js?
Yes, It is possible with esm npm packages.
require is commonjs module loader.
Browser doesn't support commonjs modules system
so that this error showed.
Method 1:
Run npm init -y and add "type" :"module" in your package.json.
create path.js file
add this line in path.js
const fullPath = await import.meta.resolve("npm-pkg-name");
const path = fullPath?.match(/(/node_modules.*)/)[0];
console.log(path);
add this line inside package.json
"path": "node --experimental-import-meta-resolve path.js",
Copy console output text. Replace package name with this copied path.
Method 2:
Install other npm package to find and replace
npm packages' virtual path to real path so that chrome browser will find it.
Install Path-fixxer
Add this line in path.js
import setAllPkgPath from "path-fixxer";
setAllPkgPath();
then run command : npm run path.
Now open browser to test it.
I have a node module that I am building, and I want it to be able to execute on the server (in nextjs server side rendering) and the client (call additional lifecycle methods in the UI). This same module also needs to work when used purely as a js library that can be included in a <script> tag on the page. This module depends on the uuid module, which has logic in it to check if it is running in a browser or server context, and use the proper random number generators/crypto libraries that are available in that context.
If I don't specify a target in my webpack config, the bundle works great in a client browser. It includes the webpack browser logic just fine. But it doesn't work in the server case - webpack removed the server capable logic in the uuid module.
If I target: 'node' in my webpack config - it executes just fine as a node module on the server and the client. It seemingly included all of the logic this time. But now it doesn't work if included just as a script tag on the page. I get ReferenceError: require is not defined from the file that depends on the uuid module.
It seems like the uuid module should handle these different environments just fine, but webpack is messing with that. How can I let that module resolve the proper implementation at runtime?
I unfortunately do not have a minimally reproducible example, or additional code to share at this time. I figured someone might have run into this with webpack (or even webpack and the uuid module) and know the solution.
I was trying to do this by building a single version of the package, but I don't think that is possible.
What is possible is building multiple versions, and then hosting the web bundle via unpkg or jsdelivr via an entry in package.json. Those entries can point to the target: 'web' version of the package, while the npm package can point to the target: 'node' version.
I have written a node module and published it as a node package. It works when I use it in backend applications (pure nodejs, no babel or transpile).
However, when I use this same npm module in the frontend (in my case a 'create-react-app') application, it breaks. Bellow is the exact error:
Module parse failed: Unexpected token (14:2)
You may need an appropriate loader to handle this file type.
The error is referring to my use of the spread operator (...). I would prefer not to have to rewrite the library, and would rather add some kind of transpiler to package my library. I haven't found a clear solution to this, they are all very convoluted.
I have tried using rollupjs, and https://github.com/insin/nwb. Neither sadly seem to be what I'm after.
Run my code:
You can install the library to your create react app using npm i cbs-proxy-client#0.0.3. And then add the line const cbsProxyClient = require('cbs-proxy-client') or import cbsProxyClient from 'cbs-proxy-client' to any of your scripts.
Advice would be appreciated :)
A library used for frontend is expected to package an already transpiled version of the source javascript. To do this, you might want to use rollup as a build process in your library to create a bundle file. You can use babel to transpile your code for desired browser support. Let's say the bundle file is saved in dist/bundle.js. Now you will modify the package.json to load this bundled file as the entry file using main parameter in package.json
If you are building using rollup or webpack, it is easy to miss that the bundled file should be prepared as a library. This means that importing the file using commonjs should be able to export correct variables. A typical webpack build removes such exports because it is supposed to work straight on a browser. This blog is in my bookmarks titled "js library steps" since I was creating my first js library.
Note that you do not need to put your generated file in version control. You can use npm files property in package.json to package your bundled files while ignoring them in git.