How to use CDN Imports in a React-Project - reactjs

My project is based on create-react-app and now I want to use Here Maps. Their documentation recommends loading the modules with CDN and I cant find any NPM packages for it. My question now is: how can I load the CDN properly?
I know there is the possibility to just put the CDN link inside my index.html file but this seems not to be the right solution I think.

After trying some things out, I found a solution for this use case.
I installed this package "html-webpack-externals-plugin".
All you have to do is read the documentation for your use case. The "CDN-Use-Case" is also described.
For accessing the functions from the external JS-API you have to put a "window." in front of the function for example like this:
const map = new window.H.Map();
Hope this helps somebody!

You can programmatically add JS script tags. Here's an example
function loadScript( {src, id, callback} ) {
if(id && document.getElementById(id)){
return; // don't accidentally re-add
}
const script = document.createElement( 'script' );
if(callback){
script.onload = callback;
}
if(id){
script.setAttribute( 'id', id );
}
script.setAttribute( 'src', src );
document.body.appendChild( script );
}
Usage example
componentDidMount(){
loadScript({
src: 'http://js.api.here.com/v3/3.0/mapsjs-core.js',
id: 'script-mapsjs-core',
callback: () => this.setState({mapsjsCoreLoaded: true})
});
}

Related

Using an url in a gulp.src array

I am trying to load a css file from an URL into a gulp.src array because that project doesn't have a npm package but still I would like to include it into my vendor.css file.
I tried this using the 'request' and the 'gulp-download' package. Neither of them seem to do what I intent to.
/// etc...
const download = require('gulp-download'); // doesn't seem to work
async function vendor_css() {
return gulp.src(
[
'./sass/src/vendor/bootstrap.scss',
'./sass/src/vendor/bootstrap-select.scss',
'./node_modules/slick-carousel/slick/slick.scss',
await download('https://cdn.jsdelivr.net/gh/ycodetech/horizontal-timeline-2.0#2/css/horizontal_timeline.2.0.css')
]
)
.pipe(sass().on('error', sass.logError))
.pipe(concat('vendor.css'))
.pipe(gulp.dest('wwwroot/css'))
.pipe(cssmin({ keepSpecialComments: 0 }))
.pipe(rename('vendor.min.css'))
.pipe(gulp.dest('wwwroot/css'));
}
So how to realize this?

FBXLoader can't find version number of fbx file

I'm trying to load a .fbx file, the loader.load function throws the following error:
THREE.FBXLoader: Cannot find the version number for the file given.
I don't know how to solve this problem. How can I check in the fbx file if it has a version number?
Below you can find the react component that I've written. When I test the app, I see only a black canvas.
I tried two different files, but have the same error for both files.
export default class myComponent extends Component {
componentDidMount() {
const camera = new THREE.PerspectiveCamera(
45,
window.innerWidth / window.innerHeight,
1,
2000
);
camera.position.set(2, 18, 28);
const scene = new THREE.Scene();
const light = new THREE.HemisphereLight(0xffffff, 0x444444);
light.position.set(0, 1, 0);
scene.add(light);
const gridHelper = new THREE.GridHelper(28, 28, 0x303030, 0x303030);
scene.add(gridHelper);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
this.model.appendChild(renderer.domElement);
const loader = new FBXLoader();
let model = new THREE.Object3D();
loader.load(
'./3DModels/MHT.fbx',
function(object) {
model = object.scene;
scene.add(model);
},
undefined,
function(e) {
console.log(e);
}
);
renderer.render(scene, camera);
}
render() {
return <div ref={ref => (this.model = ref)} />;
}
}
FBXLoader throws this error: THREE.FBXLoader: Cannot find the version number for the file given.
loader.load('./3DModels/MHT.fbx', function(object) {
...
})
instead:
const path = require(./3DModels/MHT.fbx);//写在类的外面
loader.load(path, function(object) {
...
})
I have meeted the same problem just now, you can try to debug like this:
I find the reason that my project use Mockjs which make XMLHttpRequest become MockXMLHttpRequest:
// relative code in three.js:
request.addEventListener( 'load', function ( event ) {
// if you use Mockjs, this become MockXMLHttpRequest but not XMLHttpRequest
// this.response not is ArrayBuffer ,there is the bug.
var response = this.response;
var callbacks = loading[ url ];
Here just my case which maybe help you.
Are you hosting your files in your src folder or public folder?
You should be keeping the fbx files in public folder.
The loader scans the document and parses the text to find what it needs to load. Case with working in react is this will trigger before the DOM is rendered, so it basicaly can't the version because it sees no file.
I worked it out while trying to "debug" the loader code. It turned out it was me :)
Another fbx thing is you should always use the latest loader plugin. Under this link you will find both the link to the original plugin and the example how to convert it to React module.
Hope this helps.
I had exactly the same error coming up on a ThreeJS RPG game hosted on Heroku. I eventually found a simple solution which worked for me and am posting here for any other poor soul who runs into to this issue.
The issue for me was that when I was downloading the FBX file from mixamo I was downloading just the FBX.binary file. **You need to download the fbx file with the version number **. So I just downloaded the FBX animation as FBX 7.4 and it worked. See image.
Hope this helps someone save the stupid number of hours I wasted on this...
download fbx 7.4 or 6.1

React Native. Mechanism for turning on/off console logs in one place

I have many console.log in my code.
As we know those logs slow down app a lot, so at the end of development I need to delete all of them, but of course I don't remember all the places where I have it. How can I use some wrapper for console.log which I can use, so that I could turn on or turn off all the console logs in one place? If my approach is not very good, advise me some libraries, tools, ways of doing what I need...
You can do this in the following two ways:
if(!__DEV__) {
console = {};
console.log = () => {};
console.error = () => {};
}
a better approach would be to use babel plugin transform-remove-console by
creating .babelrc file, and setting up babel transpiler.
example setup:
{
"presets": ["react-native"],
"env": {
"production": {
"plugins": ["transform-remove-console"]
}
}
}
source: https://facebook.github.io/react-native/docs/performance.html#using-consolelog-statements
Use this: https://github.com/babel/minify/tree/master/packages/babel-plugin-transform-remove-console
or you can creat a function in utils like this:
export const showLog = (tag, log) => {
console.log(tag + ' : ' + log);
};
and use showLog anywhere in your project:
import { showLog } from '../utils/utils';
showLog('VideoPlayer', response)
At the end, I've chosen the method described here - https://levelup.gitconnected.com/step-up-your-console-messaging-game-in-your-react-app-42eee17659ec
I like it best of all.
Upd: As Chmac mentioned (thanks), the link is dead. Archive link here

How to use "webpack.DefinePlugin" with React Gatsby and React-Bodymoving?

I am pretty new to React but I want to set
BODYMOVIN_EXPRESSION_SUPPORT in Webpack's Define plugin with Gatsby v1.
I followed the links below but I don't get what exactly I suppose to do...
https://github.com/QubitProducts/react-bodymovin
https://www.gatsbyjs.org/docs/environment-variables/
I made the file named .env.development and put it to src folder. the content in this file is below.
plugins: ([
new webpack.DefinePlugin({
BODYMOVIN_EXPRESSION_SUPPORT: true
})
])
The folder structures is
root--
|
|- public //where the build goes
|
|- src -- //where I develop site
|-components
|-data
|-pages
|-style
|-.env.development
What I noticed is there is a line said
/*global BODYMOVIN_EXPRESSION_SUPPORT*/
in bodymovin library and I think I just need to change that. I could modify in library directly maybe but I don't think that a best way to get around this problem. Does someone know how to set this up right?
Thanks in advance!
EDIT 2019-09-02
To use environment variables from .env files I recommend using dotenv because it's so simple. Here's an example that creates an object of all the variables in the .env file and makes them accessible on the client side (i.e in React) through DefinePlugin.
// gatsby-node.js
var dotenv = require('dotenv');
const env = dotenv.config().parsed;
// Create an object of all the variables in .env file
const envKeys = Object.keys(env).reduce((prev, next) => {
prev[`process.env.${next}`] = JSON.stringify(env[next]);
return prev;
}, {});
exports.onCreateWebpackConfig = ({ stage, rules, loaders, plugins, actions }) => {
actions.setWebpackConfig({
plugins: [
// Add the environment variables to webpack.DefinePlugin with define().
plugins.define(envKeys)
]
});
};
Here's an example of how I get the application name and version from package.json and using it in my service worker, I'm using Gatsby V2 though. Having the version in the service worker makes caching easier to handle. As you wrote, DefinePlugin is the way to go but it's a bit different when we use it in Gatsby.
We need to import the package.json file and add our custom webpack configuration in gatsby-node.js, with plugins.define() we tell webpack to use DefinePlugin:
const packageJson = require('./package');
exports.onCreateWebpackConfig = ({
plugins,
actions,
}) => {
actions.setWebpackConfig({
plugins: [
plugins.define({
__NAME__: JSON.stringify(packageJson.name),
__VERSION__: JSON.stringify(packageJson.version),
}),
],
})
}
The two defined variables __NAME__ and __VERSION__ are now accessible in my service worker sw.js:
self.addEventListener('install', function (e) {
// eslint-disable-next-line
console.log(__NAME__, __VERSION__);
e.waitUntil(
caches.open(__NAME__ + __VERSION__).then(function(cache) {
return cache.addAll(filesToCache);
})
);
});
Gatsby Reference: https://www.gatsbyjs.org/docs/add-custom-webpack-config/

create react app Configuration file after build app

I want a Config File (JSON) in root folder after build to config my app.
like Translation and API Urls and ...
Can I do this with create react app?
Create config.js or json file outside src directory and include it in index.html like
<script src="%PUBLIC_URL%/config.js" type="text/javascript"></script>
configure parameters in config.js
config.js
var BASE_URL = "http://YOUR-URL";
you can get paramenters like
const BASE_URL = window.BASE_URL;
You can store you JSON file in the public/ folder and it'll automatically provide this file when you host your Create React App.
Something like: /public/my-configuration-file.json
then when you restart your application:
localhost:3000/my-configuration-file.json
will provide you this json file.
You could create a custom hook that reads a "public" config file using fetch.
// This path is relative to root, e.g. http://localhost/config.json
const configFile = './config.json'
export function useConfig() {
const [config, setConfig] = useState(initialConfig);
useEffect(() => {
(async function fetchConfig() {
try {
const response = await (await fetch(configFile)).json();
setConfig(response);
} catch (e) {
console.log(e);
}
}());
}, []);
return config;
}
Then use it anywhere in you app
function App() {
const config = useConfig();
return (
<div>{config.foo}</div>
);
}
You'll always have an up to date non-cached version of it's data.
updating this topic with a brand new package that is available now that brings the joys of .Net Configuration to the JavaScript world: wj-config.
This package is pretty much an exact answer to what you need. Read this blog post for more information.
It is incredible to me how during over 6 years nobody filled in this gap in React (and JavaScript in general). Anyway, give wj-config a try. I think it will be a positive experience.

Resources