I'm trying to create npm package with some react hooks for my webrtc project. But found some mistakes
Current research process accumulated in github repo with reproducible example
According to project structure, problem looks like:
packages
sdk
store/call <-- contains useCall and withCall. Call useDevices inside useCall
store/devices <-- contains useDevices and withDevices
webpack.config.js
entry -> store/call
entry -> store/devices
ui
dynamic-component
useDevices <-- return store
useCall <-- return store
useDevices <-- return undefined. PROBLEM HERE
What already try:
use dependOn - after this, ui failed with import bundle. Explained in webpack issue, but not result
move store/devices into separate subproject with webpack.config.js and import it in sdk. Add it into webpack "externals" in sdk. But nothing changed :(
Can anyone advice how to debug this or configure for valid results?
Related
I've created a few apps that follow the same pattern as the react-microfrontend projects listed on the Single-spa examples page. However, these examples are not using TypeScript.
I am receiving a TS error when App2 tries to import a function that exists in App1, because App2 is unable to find the typings for the App1 object. And this makes sense to me, since the importmap.json that is referenced in the index.html file of the root-config project only has a URL listed for the .js file of each microfrontend. I really don't want to add #ts-ignore statements everywhere, and I also don't want to do cross-app communication without being type safe.
An example of what I'm referring to:
This file in the Planets app references the Button component from the Styleguide app. I am unable to build this unless I place a #ts-ignore on the line before the import statement, because my Planets app cannot find the type declarations for Styleguide.
I am very new to import maps and SystemJS in general, so if anyone could point me in the right direction, I'd appreciate it. I've actually gone through the trouble of building my Styleguide as a regular npm library and just including it as a dependency in the Planets package.json file... which kind of defeats the whole purpose of using Single-spa in the first place.
importmap.json
{
"imports": {
"#react-mf/planets": "//localhost:9000/react-mf-planets.js",
"#react-mf/styleguide": "//localhost:9001/react-mf-styleguide.js"
}
}
page.component.ts
// #ts-ignore
import { Button } from "#react-mf/styleguide";
...
render() {
return (
// Unable to view the available props
<Button label="Hello World" />
);
}
Unfortunately no, they cannot be shared via the import map because that operates in the browser, and browsers do not understand TypeScript syntax.
Your alternatives are:
Publish your module's types to an npm registry and npm install it into each dependent microfrontend
One caveat here: you will need to update this with every new publish of the shared module, but that can be automated with various tools such as renovate
Mock the utility module's types
More info can be found at this Github issue: https://github.com/single-spa/single-spa/issues/609#issuecomment-665132965
I'm working on Next.js and React-Native-Web. I managed to run them together following the official Next.js example but when I'm trying to use the Animated package from the react-native it fails with Error that the requestAnimationFrame isn't defined. Basically this functionality does the node_modules package but I set the alias in webpack to translate all react-native requires to the react-native-web so even the node_modules package should use the react-native-web.
Any suggestions on how to solve it?
ReferenceError: requestAnimationFrame is not defined
at start (...node_modules\react-native-web\
dist\cjs\vendor\react-native\Animated\animations\TimingAnimation.js:104:11)
enter code here
Thanks for any help!
The problem is in the missed RequestAnimationFrame functionality at the server. This error happens when Next.js tries to render the component during SSR.
Unfortunately, there is no polyfill, etc. for such purpose so I just decided to use the Next.js dynamic imports for a Component that has animation functionality.
Next.js Official documentation
My own case оust to show how code looks:
import dynamic from 'next/dynamic';
const AutocompleteDropdown = dynamic(
() => import(
'myAwesomeLib/components/dropdown/autocomplete/AutocompleteDropdown'
),
{
ssr: false,
}
);
Now you can use the AutocompleteDropdown as the standard JSX component
I'm coding an App with React Native Web and NextJS 12, and in 2021 I encounter this problem and I fixed it, but now I know my fix was only for Next Dev, because it returned for Next Production Build.
Solution details:
No Dynamic import (which is useful too, but can be annoying when having lot of components using it)
Using RAF polyfill and Webpack ProvidePlugin.
Main thing to have in mind is that next.config.js with webpack 5 is going to check the codes first before even reach next entry points _documents.js and _app.js. It means that, you can put polyfill in those entry point files, it will still raise error of RAF undefined. You have to make requestAnimationFrame ready for config check.
DEV approach that will work on Next DEV only. Install RAF package https://www.npmjs.com/package/raf and In next.config.js add codes:
const raf = require('raf');
raf.polyfill();
This will add requestAnimationFrame and cancelAnimationFrame function to global and window object if they don't have it. In our case, it would add it in global for NodeJS.
But this solution won't work when executing npm run dev. I don't know why, if anyone knows why Next or Webpack 5 act differently from DEV to PRODUCTION, let me know.
Complete Solution:
Use ProvidePlugin config of webpack 5 https://webpack.js.org/plugins/provide-plugin/ . Create a file to use as modules, let's say: raf.js in root project or anywhere you want:
const raf = require('raf');
const polys = {};
raf.polyfill(polys);
module.exports = polys.requestAnimationFrame;
And in next.config.js use it inside webpack: () = {} like:
webpack: (config, options) => {
// console.log('fallback', config.resolve.fallback);
if (options.isServer) {
// provide plugin
config.plugins.push(
new options.webpack.ProvidePlugin({
requestAnimationFrame: path.resolve(__dirname, './raf.js'),
}),
);
}
And now, it's up to you to adapt to your existing config logic. By doing this, in Production Build, NextJS is injecting the requestAnimationFrame function in Server Side everywhere a module is using it.
I have a React app created using Create React App that was running fine until today. Something must have updated the last time I installed a new package. Anyhow, so whenever I try to start the app, it complains that there are .ts files (within node_modules folder) and forces me to install TypeScript.
Is there any way to stop this behaviour? Because currently, installing TypeScript just opens a bottle of worms, where I need to resolve the TypeScript errors that arises.
Also, as the screenshot suggests, removing the tsconfig.json file doesn't resolve the issue, it gets automatically created on every run..
Currently because it's preventing me to work, I've done the following modification until they fix it on the Create React App:
Current solution until they fix the create react app
On the file node_modules/react-scripts/scripts/utils/verifyTypeScriptSetup.js, find the definition of verifyNoTypeScript() (line 24). Replace the function to the following:
function verifyNoTypeScript() {
return true;
}
I just want to display the version value of my package.json file within the footer of my app, but have no idea how to do that. I've read you could access those properties with process env object. Is it correct?
If you're running your app within NodeJs, you can access it by doing
process.env.npm_package_version
With ES6, you can also do
import {version} from './package.json';
The correct answers will be here in example:
Answer (this code include package.json file and get version)
const { version } = require('./package.json');
Answer
const version = process.env.npm_package_version
Please don't use JSON.parse, fs.readFile, fs.readFileSync and don't use another npm modules it's not necessary for this question.
I'm writing a simple Twitter app using react-native. Using twit module to get twitter feeds and stream. Below is the code, it works fine node. However, when included into my react-native app, seeing error "Requiring unknown module "crypto"". Dependency seems to be myapp->twit->oauth->crypto (thats part of node v0.12.2). Any suggestions to get this working inside react-native environment?
var Twit = require('twit')
var T = new Twit({
consumer_key:''
, consumer_secret:''
, access_token:''
, access_token_secret:''
})
var filtered_tweets=[];
var error;
var isSuccess=false;
function getTweets(searchString){
T.get('search/tweets',{q:searchString, count:100}, getResponse);
}
function getResponse(err,data,response){
if(err) {
handleGetErr(err);
}
handleGetData(data.statuses);
}
function handleGetErr(err){
enter code here
error = err;
}
function handleGetData(data){
data.map(function(tweet){
var twit={
twit:tweet.id,
created_at:tweet.created_at,
text:tweet.text,
retweet_count:tweet.retweet_count,
favorite_count:tweet.favorite_count
};
filtered_tweets.push(twit);
});
console.log(filtered_tweets);
isSuccess=true;
}
getTweets("#sahaswaranamam");
module.exports = getTweets;
![attached][2]
The crypto module is a built-in Node module; React Native runs JS on JavaScriptCore (when on the device or simulator) and on Chrome itself (when using Chrome debugging), so modules that depend on built-in Node.js modules won't work. See the JavaScript Runtime section of the React Native docs for more info.
I'm not sure how hard it would be to integrate into a React Native app, but browser module bundlers like Browserify often have browser versions of core Node.js modules, like this one for crypto.
If you are using rn-nodeify as #emmby suggests, then you can use react-native-crypto. Instructions from the README:
Install
npm i --save react-native-crypto
# install peer deps
npm i --save react-native-randombytes
react-native link react-native-randombytes
# install latest rn-nodeify
npm i --save-dev mvayngrib/rn-nodeify
# install node core shims and recursively hack package.json files
# in ./node_modules to add/update the "browser"/"react-native"
# field with relevant mappings
./node_modules/.bin/rn-nodeify --hack --install
rn-nodeify will create a shim.js in the project root directory
// index.ios.js or index.android.js
// make sure you use `import` and not require!
import './shim.js'
// ...the rest of your code
But rn-nodeify also states:
If you're looking for a saner approach, check out ReactNativify. I haven't tested it myself, but I think philikon will be happy to help
With ReactNativify you create a rn-cli.config.js and then in a transformer.js you let Babel transform bundle dependencies using babel-plugin-rewrite-require:
// The following plugin will rewrite imports. Reimplementations of node
// libraries such as `assert`, `buffer`, etc. will be picked up
// automatically by the React Native packager. All other built-in node
// libraries get rewritten to their browserify counterpart.
[require('babel-plugin-rewrite-require'), {
aliases: {
crypto: 'crypto-browserify',
// ...
},
throwForNonStringLiteral: true,
}]
(Note: You can also do this in without these 2 js files directly in .babelrc)
(Note2: Though ReactNativify is the cleaner way, it is still giving me issues wiring up crypto.getRandomValues for production-use in RN. See this question)
You can use the rn-nodeify module to get crypto on react-native.
Add rn-nodeify to your devDependencies in package.json:
"devDependencies": {
"rn-nodeify": "^6.0.1"
}
Add the following to the scripts section of the same file:
"scripts": {
…
"postinstall": "node_modules/.bin/rn-nodeify --install crypto --hack"
}
Be aware that rn-nodeify will modify your package.json.
More information available here: https://www.npmjs.com/package/rn-nodeify
React Native packager uses Babel under the hood. This means that you can use babel-plugin-rewrite-require Babel plugin to rewrite all require('crypto') calls to require('crypto-browserify'), assuming that the latter is installed in your node_modules.
As of January 2016, you can use .babelrc file to define optional configuration, so this becomes really easy. First, install the dependencies:
npm install --save crypto-browserify
npm install --save-dev babel-plugin-rewrite-require
Then add plugins config to your .babelrc file:
{
"presets": ["react-native"],
"plugins": [
["babel-plugin-rewrite-require", {
"aliases": {
"crypto": "crypto-browserify"
}
}]
]
}
Restart the packager and that should be it.
This is the same approach that ReactNativify uses, except that here we use .babelrc instead of defining custom transformer. When ReactNativify was written, it was not supported, so they had to go with more complex solution. See this file from ReactNativify for almost complete list of node polyfills.
I was having the same issue when implementing the Twilio package in my React Native app, and having React Native break over the crypto dependency.
As a work around I ended up creating a separate, stand alone Node/Express app to act as my server and take care of the Twilio logic I had. That way I removed all Twilio logic from my React Native app and moved it to Node. I then just called my Express route in React Native using fetch, which triggered the functionality I wanted to happen with Twilio. If you're unfamiliar with fetch here's a good starting point -
Making AJAX calls with Fetch in React Native
In addition, here's my question on the crypto dependency breaking my app:
twilio-react-native-unable-to-resolve-module-crypto
As far I can see amazon-cognito-identity-js uses crypto-js 3.3.0 without any additional magic... If that version of the package works then perhaps try that.
After having tried a bunch of these solutions and never really having been satisfied with any of them (some didn't even work), I managed to stumble upon react-native-quick-crypto, which honestly worked much more effortlessly than trying to lift the existing crypto library to the front-end