React different homepage by environnement Best practices - javascript

I have a different homepage in all my environment. One for staging, one for development. The issue is in each environment, I need only 1 homepage and not the other one.
Actually I have a temporary solution : with a 'if' I test and it's load the good one but I think that's not a good idea because I have to import all of my homepage when I am doing this.
All homepages are currently built when you import the files and there is some conflict with my CSS.
Maybe I need to change the webpack config, if you have some links to help me.
Or if you have some good practices to do it, that's sure be helpful !
import developmentHomePage from './developmentHomePage.jsx'
import stagingHomePage from './stagingHomePage.jsx'
const mapStateToProps = state => {
const currentEnvironnement = process.env.name
if (currentEnvironnement !== 'development') {
homePage = developmentHomePage
} else {
homePage = stagingHomePage
}
return {
homePage
}
}

you can fill homepage dynamically with environment variables. Check the given link to get the hint:
dynamically fill homepage

Related

Importing / exporting Javascript Object Properties

I support a relatively complex legacy codebase, but am looking to modernise it a little by bringing in Webpack so that we'd have import & export capabilities in JS.
The problem I'm having is that we use a global object called App where we define and add different properties depending on the page. So for example we have the following file where we instantiate App (loaded on all pages):
app.js
const App = (() => {
const obj = {
Lib: {},
Util: {},
// etc
}
return obj;
})();
Then in another file we add to App.Lib just for the specific page that needs it:
lazyload.js
App.Lib.Lazyload = (() => {
// lazyload logic
})();
We simply concatenate the files during the bundling process, but obviously this is not ideal as none of the files have no knowledge of what goes on outside of it.
Exporting only seems to work for the top level object (where the object is defined), so anything I add to it elsewhere cannot be exported again. For example if I add export default App.Lib.Lazyload; at the end of lazyload.js and then try to import it elsewhere it will not import the Lazyload property.
Is there any way to get this to work without major refactor? If not, would you have any suggestions about the best way to handle it?
I don't think you can import Object.properties in JS. If you want to bundle specific packages (say Lazyload) for packages that need them, you might try:
//lazyload.js
export const LazyLoad = {
//lazyload logic
}
then somewhere else...
import {LazyLoad} from 'path/to/lazyload.js';
// assuming App has already been created/instantiated
App.Lib.Lazyload = LazyLoad;
Using Export Default...
//lazyload.js
const LazyLoad = {};
export default LazyLoad;
then...
import LazyLoad from 'path/to/lazyload.js';
App.Lib.LazyLoad = LazyLoad;
You can find help with Imports and Exports at MDN.

Optionally import Component in Vue

I have several menu types and want to configure the type of menu to be used in .env.local for example: VUE_APP_MENU_TYPE=2
In my javascript file I have the following:
let menu = false;
if (process.env.VUE_APP_MENU_TYPE === "2") {
menu = require("./type2/Type2.vue");
}
if (menu === false) {//default menu if env is missing
menu = require("./default/Default.vue");
}
export default menu;
This will result in an error Failed to mount component: template or render function not defined.
I can do the following:
import Default from "./default/Default.vue";
import Type2 from "./type2/Type2.vue";
let menu = Default;
if (process.env.VUE_APP_MENU_TYPE === "2") {
menu = Type2;
}
export default menu;
This will work but all menus are compiled in the code, including menus that will never be used since VUE_APP_MENU_TYPE is known at compile time and will never change until you recompile.
Is it possible to import a component dynamically at compile time?
Try menu = require("./type2/Type2.vue").default;
Explanation taken from this answer
when dealing with ES6 imports (export default MyComponent), the exported module is of the format {"default" : MyComponent}. The import statement correctly handles this assignment for you, however, you have to do the require("./mycomponent").default conversion yourself. If you want to avoid that, use module.exports instead of export default
Fort second part of question...
Is it possible to import a component dynamically at compile time?
Really never tried but I have my doubts. Webpack is not executing the code when building. It just scans it for some patterns.
It scans for require() so it know what modules should be included in the bundle
DefinePlugin is replacing strings like process.env.VUE_APP_MENU_TYPE with values from env files so it make code look like if ("3" === "2") {
Other plugins are able to detect that if ("3" === "2") { is never true and eliminate "the death code"
Real question if what happens first - if require scanning happens before death code elimination, you will end up with all possible menu components in the bundle. But unfortunately I don't know - You'l have to try
On the other hand using dynamic async components (as mentioned in other answers) is sure bet. Yes, Webpack will build all possible menu components but each with it's own js chunk (js file in dist folder). If the app loads just one of them, it's seems fine to me (note that the loading will be async - at runtime - so it means one more server request)
I think that loading the component dynamically is the best option you have.
https://v2.vuejs.org/v2/guide/components-dynamic-async.html
I could have solved this with a webpack setting.
In vue.config.js
const path = require("path");
module.exports = {
configureWebpack: {
resolve: {
alias: {
MENU: path.resolve(
__dirname,
(() => {
if (process.env.VUE_APP_MENU_TYPE === "2") {
return "src/components/header/CategoriesMenu/Type2/Type2.vue";
}
return "src/components/header/CategoriesMenu/Default/Default.vue";
})()
),
},
},
},
};
In src/components/header/CategoriesMenu/index.js
import menu from "MENU";
export default menu;
But to be honest, I like the require better.

Making a classic javascript 3rd party app work within an existing react/node app

I have an app that does video chat already built in react/node.
I am trying to add a feature that opens up a shared whiteboard that the participants in the video chat can use.
I did some research and AwwApp is the one I like the best for this shared whiteboard functionality.
AwwApp does not have react specific code examples or modules. However, they do provide a straightforward widget that uses a .js file they host.
I am trying to implement this classic javascript widget into my existing react app and running into some issues - likely due to something simple that I'm just missing.
Here's the simple AwwApp quick start with the js file to include and how to call it the classic way: https://awwapp.com/apis/V2/docs/
Here is the code from my "AwwBoard.js" file that I am using to create a component that renders the whiteboard anywhere I want to import it and return in react:
import React, { Component } from 'react';
import Cookies from 'universal-cookie';
import Script from 'react-load-script'
// Get cookie for meeting room that this whiteboard instance will appear in. Will be used after I get whiteboard working.
const cookieMgr = new Cookies();
const room = cookieMgr.get('room');
// The main AwwApp external javascript file to include, I use react-load-script to load it below
const awwAppScript = 'https://awwapp.com/static/widget/js/aww3.min.js';
// Create a React component I can display using <AwwBoard /> anywhere I want a whieboard to appear
class AwwBoard extends Component {
handleScriptCreate() {
this.setState({ scriptLoaded: false });
};
handleScriptError() {
this.setState({ scriptError: true });
};
handleScriptLoad() {
this.setState({ scriptLoaded: true });
};
// Function I created to render the board. Per https://awwapp.com/apis/V2/docs/ - should embed the whiteboard widget in the div with id aww-wrapper below
handleBoardRender() {
var aww = new AwwBoard('#aww-wrapper', {
});
return aww;
};
render() {
return (
<div id="aww-wrapper">
<Script
url={awwAppScript}
onCreate={this.handleScriptCreate.bind(this)}
onError={this.handleScriptError.bind(this)}
onLoad={this.handleScriptLoad.bind(this)}
/>
{this.handleBoardRender()}
</div>
)
};
};
export default AwwBoard;
Any guidance would be greatly appreciated. I'm sure there is an easy way to do this, I'm just not seeing it after doing some of my own trial and error.
Thanks!

Is it possible to auto import JS files for all react components?

I have created a logging utility function that I plan to use on 99% of components in my site. I am wondering if it is possible to access this file without having to write "import { logger } from 'utils/logging';" for every React component? Sort of like an auto import?
I am using create-react-app.
If I understand your requirement properly, you want the similar usage of console.log (without importing console), then below is something you can try.
In your index file, set it as a global object(for server side js) or window object (for client side js). So that , it can be accessed anywhere.
We had something like this with a mmiddleware(using redux-logger package):
const logger = require('redux-logger').createLogger
return middleware.concat(logger({
collapsed: true,
duration: true
}))
Hope this helps!
What you're trying to do sounds like a bad way to do it. I think the best solution if you need custom data logged, would be to create/add a middleware. Or in React's case maybe a wrapper component. I'm not sure.
Otherwise look into React / Redux Dev Tools Extension.
https://github.com/facebook/react-devtools
https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi
Edit:
If you want to ignore good practices then you can do this:
// in index.js or app.js or wherever
import { logger } from 'utils/logging'
// if you have an env for development use it here
process.NODE_ENV = 'development' && window.logger = logger
// or just
window.logger = logger
// SomeComponent.js
window.logger()

How to conditionaly load components?

I have an angular 2 app which every client can slightly modify before receiving the production version. Because the differences are not too big, all instances of app are build of the same source code. To achieve diffrent builds i use webpack with NormalModuleReplacementPlugin,
webpack.config
new webpack.NormalModuleReplacementPlugin(/(.*)ENV(.*)/, function(resource) {
var componentName = resource.request.slice(resource.request.lastIndexOf('/') + 1, resource.request.indexOf('ENV'));
if(componentName in buildConfig){
resource.request = resource.request.replace(/ENV/, buildConfig[componentName]);
}
else {
resource.request = resource.request.replace(/ENV/, '');
}
})
import
import { RegisterComponent } from '../register/registerENV.component';
this works but also causes compiler and ide errors, which are preety annoying. So does anyone know better way to conditionaly build app with posibility to swap components and also not load unnecessary code into the bundle?
English is not my mother tongue, please excuse any errors on my part.

Categories

Resources