Building configurable react app with additional environment variable - javascript

I'm building an app that has some variations. The core of an app is the same but for now, I need to develop some parts of the app in different way, like another color scheme, different photos etc.
My Question is: Is there any possibility to build an app with specified instance by env variable? For example, I have set of photos provided as below.
[{
"photo1":{
"path":"my_path_to_file1",
"instanceToDeploy":"instanceABC"
}
},
{
"photo2":{
"path":"my_path_to_file2",
"instanceToDeploy":"instanceCBA"
}
}]
And for now, I would like to build my app like
npm run build instanceCBA
After this operation, I want to have build version of an app only with photos/whatever I will include in build command.
If elements are not tagged - I would like to build them anyway.
Is there any way to do this in React or something similar to this idea?
My previous attempt to this, was building the app on a few separated branches. Of course, unique changes was written without affecting another instances, but in situation when I've written the code which have to be on all instances - I have to actualize all the branches.
My main desire is to build some configurable elements that depends of choosen instance in my app.
Thanks for all possible help.

There are several options of how you can do it:
#1 (the easiest way)
If you use create-react-app boilerplate for your project you can use '.env' file for setting environment variables. You can find more info about it here: https://create-react-app.dev/docs/adding-custom-environment-variables/
#2
You can pass the parameter from your scripts that you defined in the package.json file. For example, let's say your scripts section looks like this:
"scripts": {
"build": "webpack --myInstance instanceCBA",
}
In this case in the webpack.config file you can read your parameter via process.argv array:
const instancePrefixInd = process.argv.indexOf('--myInstance');
let instance = '';
if (instancePrefixInd >= 0) {
instance = process.argv[instancePrefixInd + 1];
}
Then you can use this value in you webpack.config to specify details of the build or pass it directly to the app via setting 'process.env' variables (e.g process.env.MY_INSTANCE)

Related

What's the proper way of setting environment variable in Netlify functions?

What's the proper way of setting environment variables in netlify? I would like to be able to set different values for the variables depending on the environment.
Pseudo code:
let host;
if (process.env.GATSBY_CUSTOM_CONTEXT === 'production') {
host = process.env.PRODUCTION_HOST
} else if (process.env.GATSBY_CUSTOM_CONTEXT === 'development') {
host = process.env.DEVELOPMENT_HOST
}
I have tried passing env variable thru CLI, like GATSBY_CUSTOM_CONTEXT=production gatsby build and I also tried using same command with cross-env.
My other attempt used netlify.toml:
[build]
base = "/"
publish = "public"
command = "yarn build"
functions = "src/functions"
[context.production]
[context.production.environment]
GATSBY_CUSTOM_CONTEXT = "production"
All of these options worked with netlify dev locally, but in production GATSBY_CUSTOM_CONTEXT is always undefined.
The reason you can't resolve the environment variables in your Netlify functions is because as of the time of your question, Netlify does not transfer the environment variables from the netlify.toml file.
You must put them into the admin panel in your site settings in the app.netlify.com dashboard.
Unfortunately, what you're looking to doesn't seem to be currently supported. Though they provide an alternative approach.
I found this snippet on their docs:
CALLING ENVIRONMENT VARIABLES
Using environment variables directly as
values ($VARIABLENAME) in your netlify.toml file is not supported.
However, the following workflow can be used to substitute values in
the file with environment variable values, assuming you are only
trying to change headers or redirects. The rest of the file is read
BEFORE your build — but those sections are read AFTER the build
process.
Add a placeholder like HEADER_PLACEHOLDER somewhere in the netlify.toml redirects or headers sections.
Create an environment variable, for example PROD_API_LOCATION, with the desired value. You can create environment variables in the
toml file or in our UI. You might use the latter to keep sensitive
values out of your repository.
Prepend a replacement command to your build command. Here’s an example for a site using yarn build to build: sed -i
s/HEADER_PLACEHOLDER/${PROD_API_LOCATION}/g netlify.toml && yarn build
Taken from here: https://www.netlify.com/docs/netlify-toml-reference/

How to load javascript es6 module determined at runtime?

I am developing a SPA which contains multiple dashboards. Each dashboard is a set of Web Components respecting a layout. These components are not known statically. They are determined at run-time.
What I want to achieve is the following scenario:
Application starts.
The application performs XHR to fetch dashboards representations from a REST service.
User sees dashboards listed by name.
User clicks on a dashboard item. (say dashboard 1)
The application determines the necessary components needed to load dashboard 1 (web components)
Load web components and their dependencies.
I am pretty aware of loading web components dynamically which was answered here
My actual problem is
how to load a web component with their dependencies at run-time
without having to load duplicate dependencies?
Are there any module formats or practices to follow when packaging the
web components?
If you have a mapping from dashboard to the module that implements it, then you can just dynamic import() the necessary module. The JS module system will take care of not loading modules that have already been loaded, so common dependencies like lit-element will only be loaded once.
This deduplication works based on URL, so you have to make sure that you have one copy of a dependency installed via npm. npm dedupe will attempt to deduplicate your node_modules/ folder, and npm ls will let you see the dependency tree.
All current browsers support dynamic import(), and most bundlers do too - as long as the argument is a string constant. This means that you can't compute the module URL based on the dashboard if you want to use a bundler. You need something like:
const dashboardLoaders = {
'dash-1': () => import('./dashboards/dash-1.js'),
'dash-2': () => import('./dashboards/dash-2.js'),
// etc...
};

Combining Static Sites + Client Side Rendering (React, Gatsby)

I want to build a web app with React.
When users visit the site, they will see a Landing Page, can go to a Pricing Page, an About page, a Blog. etc. They can also Sign Up or Log in and then there's the actual app. I would like render certain pages (Landing,Pricing,About,Blog) statically, but would like to leave everything behind the SignUp/Login-Wall client-side rendered.
(First, because it cannot be static, since this is dynamic content. And also, because I do not care about SEO here anyways, so a major reason for next.js falls away, since the app is behind a SignUp/Login Wall anyways.)
Questions: First of all: Does this make sense? And secondly: How could I implement something like this? I haven't found anything online! Is this unheard of? I would like to use Gatsby.js for my static content, but I am not sure how to bring the client-side-rendered bit into the mix. I have worked with create-react-app before, which does client-side-rendering, - but I am not sure how I would go about the implementation?
I will try to explain the process behind jamstack-hackathon-starter (which #ksav commented).
It is a starter template for gatsby that allows you to save static pages in-
conjunction with dynamic pages (client-side react app) - a "Hybrid Gatbsy App".
Manual Steps:
1. Create a folder src/app which will contain your client-side react app.
2. Create a file in src/pages called app.js, with the following contents:
// I'm using create-react-app's structure
import App from '../app/src/App' // make sure this path corresponds to your path
export default App
Now install gatsby-plugin-create-client-paths:
npm install --save gatsby-plugin-create-client-paths
Configure it by adding it to gatsby-config.js like so:
plugins: [
{
resolve: `gatsby-plugin-create-client-paths`,
options: { prefixes: [`/app/*`] },
},
...
This will result in everything within /app to only be rendered in the browser (ie client-side).
Go to your browser after building (gatsby develop) and check /app
According to npmjs
The plugin gatsby-plugin-create-client-paths is deprecated.
https://www.npmjs.com/package/gatsby-plugin-create-client-paths
This plugin's functionality is now built-in to Gatsby.
Use the File System Route API: https://gatsby.dev/creating-client-only-routes.
This package will no longer receive updates.

Best way to make webpack run a script in browser?

I want Webpack to execute a script (that is provided by my npm package) in the browser, without needing to include that script in my app. Currently, I am using webpack.config.dev.js to force it, like this:
module.exports = {
entry: [
paths.appIndexJs,
"./node_modules/my-dev-package/client.js"
]
}
client.js contains an IIFE that modifies the DOM. I want to avoid having to add conditional logic to my application to check for the environment, when I really just need something appended to the DOM in development. Is there a more standard way to get this same effect, without having to import client.js inside my app and conditionally run it there?
I am new to webpack, so if there is a standard way to do this or a commonly used plugin, that's what I'm looking for.

Create directories and files from a template for rapid development with node/npm

I am trying to setup a shortcut to generate new components. For example if I had a bunch of React or Angular components that had a particular dir/file structure and included sample code for a new component. Is there a way to do this with node? It's quite time consuming to keep adding the same directories and files whenever I need to create a new component.
I usually do this in a convoluted but workable way with bash and aliasing but would like to use node, ie. npm run component myNewComponent where 'myNewComponent' would act as the function name within a myNewComponent.js file etcetc
I would have an example directory structure templated somewhere that node could pick up from or have it hardcoded in the node script file itself.
Yeoman does this with generators, but I would like to achieve it purely through node/node modules and full control over the code output and locations.

Categories

Resources