I have four or five small web apps that I build and maintain for a small group at work. For the most part, they have the same layout and file structure. A lot of the files are the exact same across the apps. Here's an example index.js file that's the same in every apps' src/ directory.
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
if (process.env.NODE_ENV !== 'production') {
console.log(`Environment: ${process.env.NODE_ENV}`);
}
const root = document.querySelector('#root');
ReactDOM.render(<App />, root);
Copying and pasting works fine until I need to update something. A few months ago I started changing my React class components over to functional components with hooks. The only problem is I have to make that same change for every version of that file in every site.
I tried using bit and I thought about creating a local NPM package, but those aren't ideal options. I'd have to import each file and that doesn't really work the way I need. (I guess I could import the very first index.js file, but it doesn't seem like an ideal solution.)
I want to be able to edit a file in app A and next time I go back to work on app B be able to see the changes made to the file in A and pull them into B. That way I can make each of the shared files/components dynamic enough to work for all my apps. If the changes made on the file in app A don't work for app B, I can rework the file in app B and pull the changed next time I work on app A.
I hope this makes sense. Thanks in advance for any help you can offer!
I believe git submodules could be a valid option for you, especially for push/pull changes part.
Related
I created an api. And for him, I created a one-page interface using vuecli. My plans are to embed it in the projects I need. The question is what needs to be done to export the written application and reuse it where necessary?
The structure of the project is shown in the screenshot.
src/main.js - connect and configure axios
src/App.vue - I describe the main component of the application
(maybe I need to put it in a separate component in the components
folder)
src/components/OneDay.vue is the second component that is mainly
called src/App.vue several times.
src/mixins/dateHandler.js - several functions common to the two
components, which are connected as mixins.
I have not modified any other files. How can I prepare this correctly so that I can connect these components to my other applications using composer? I connect, configure some variables (api address, for example) and display it in the right place on the page - this is how I see it.
You can try to create a web component using VUE CLI 3 to use it later in a different code base. Just make sure your main.js file looks like this
import Vue from 'vue';
import wrap from '#vue/web-component-wrapper';
import VueWebComponent from './components/VueWebComponent';
const CustomElement = wrap(Vue, VueWebComponent);
window.customElements.define('my-custom-element', CustomElement);
and build it using vue-cli-service build with --target wc
You can read more precise instructions there:
https://github.com/vuejs/vue-web-component-wrapper
https://vuejsdevelopers.com/2018/05/21/vue-js-web-component/
Hi I am creating an app on reactjs, which is canvas based, It require Createjs library, I am new for Reactjs I am not getting perfect idea how do this so I tried 2 ways one is using NPM install and other one is I kept my js into one folder and tries to import from there but nothing works for me, here my code
way 1 with npm install,
import createjs from 'createjs';
way 2 import downloaded js file,
import createjs from '../assets/js/createjsmin';
randomly I tried
import * as createjs from '../assets/js/createjsmin';
but nothing works for me
I add relative path to index.html and got Createjs library code into componentWillMount() using window.createjs, dn't know but I feel it can work to add all ramdom libraries in react.
So I made it work by installing this specific dependency
"#createjs/easeljs": "^2.0.0-beta.4",
And In my Component file I am importing them like this
import { Stage, Shape, TraceShape } from '#createjs/easeljs';
I am using Gatsby and importing jquery.
When I run Gatsby build I get the following error:
WebpackError: jQuery requires a window with a document.
This is due to Gatsby doing server side rendering.
I have read through a number of issues on GitHub (this one being the best one I could find).
My code looks like the following:
import React, { Component } from 'react'
import Link from 'gatsby-link'
import LandingScreen from '../components/LandingScreen'
import $ from 'jquery'
import 'fullpage.js/dist/jquery.fullPage.js'
import 'fullpage.js/dist/jquery.fullpage.css'
class TestPage extends Component {
componentDidMount() {
$('#fullpage').fullpage({
verticalCentered: false
});
}
render(){
return (
<main id="fullpage">
<LandingScreen />
</main>
)
}
}
export default TestPage
This is breaking so I tried the following based on the GitHub thread above, but this also fails:
if (typeof window !== 'undefined') {
import $ from 'jquery'
}
Can anyone advise how to import jquery?
Gatsby's components will run on both Node (no window object there) in order to produce static HTML and on the client's browser as React components. This is why you get this error.
The plugin you are trying to use needs to run only on the client because it needs the actual viewport dimensions to operate. Gatsby has a special API for this that you can use to run the plugin only on client side. A quick solution would be to load jQuery there and initialize your plugin on onClientEntry.
I would also suggest you find a more lightweight plugin that does the same thing without the jQuery dependency. It's a pity to use jQuery in a React stack. Maybe somebody else can recommend one.
Peter, I recently reported this to jQuery maintainers, but they politely told me... well... to kick rocks. Would be good, if you could badger them about this a bit, too.
Currently jquery absolutely requires window object, so it won't work on Node.js as a dependency. (with one exception: if you don't need a global jquery object, but just a local instance in one module, you can manually initialise it with JSDom, but that's probably not your use case)
Your way around this whole problem is that you don't actually have to import jQuery or its plugins on server side. So my approach was to create 2 separate entry point files - app.jsx and server.jsx - for client bundle and server-side bundle respectively and Layout.jsx as a shared root component.
app.jsx and server.jsx are entry points for client-side bundle and server-side bundle respectively, while Layout.jsx contains shared code with html.
I import jquery only in app.jsx bundle, so on client side it is present. On server side it is never imported and not included in server bundle.
You can take a look at my blog's code, how I set up Webpack in it and how do server rendering.
I am new to React Native, I'm following a video tutorial for beginners. I'm developing on windows 10 and using React Native version 0.49.1 . In the tutorial I'm following there are two index files: index.android.js & index.ios.js.
As I understand those file are untied now to index.js file,
I got it from this question that was asked.
Nevertheless, I still want to work with two separate index files, but I don't know how to do so - do I have to delete App.js file and index.js files?
And if so, what should be the content of index.android.js & ios files?
I would appreciate an explanation or a quick guide on how to do it.
Thanks in advance :)
For projects created with react-native init, an index.js file is still generated, and looks something like this initially:
import { AppRegistry } from 'react-native';
import App from './App';
AppRegistry.registerComponent('YourProjectName', () => App);
Manually adding App.ios.js and App.android.js in the same directory will allow you to include unique code for each platform, as it follows the pattern for platform-specific extensions. However, it won't be enough to have either one or the other. You need to include both otherwise the code splitting won't take effect (and will default to whatever is present in App.js).
So to answer your question, yes you need to delete App.js and replace it with android.App.js and ios.App.js. Then restart the React Native packager terminal window for your simulator or device to detect the change.
I have a React application created using the create-react-app module. I have recently been asked by a client to integrate with oidc. For this purpose I'm using redux-oidc, as I already have redux working in my app as well.
We managed to integrate my application into their Identity server and I'm able to sign in and get the user token stored in redux. The problem is that I'm struggling to setup silent renew in my create-react-app application as I have to add an additional entry point. Is there a way to add an additional entry point to silent_renew/index.js without ejecting create-react-app?
Currently I've create a folder called silent_renew containing an index.js file. This folder also contains a silent_renew.html file with not much in it (See: example app similar to my folder structure).
Since the landing page for silent_renew is a just a simple html page, you could bypass webpack. Just put the following file in the public folder. Also, include a copy of the oidc-client.min.js library in the same folder.
public/silent_renew.html:
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<script src="oidc-client.min.js"></script>
<script>
new Oidc.UserManager().signinSilentCallback().then()
</script>
</body>
</html>
This works at my site in the develepment config. For the production config I have the following in mind (I did not test it yet but I'm pretty confident this is the way forward...).
public/index.js
const express = require('express')
const path = require('path')
const app = express()
app.use(express.static('.'))
app.use((req, res, next) => {
if (path.extname(req.path).length > 0) {
next()
} else if (path.dirname(req.path).indexOf('silent_renew') > -1) {
req.url = '/silent_renew.html'
next()
}
else if (path.dirname(req.path).indexOf('callback') > -1) {
req.url = '/callback.html'
next()
} else {
req.url = '/index.html'
next()
}
})
app.listen(3000)
As soon as create-react-app supports multiple entry points (I hope this happens soon for enterprise login scenario's) this code becomes obsolete.
You can also take the approach of loading the main bundle in the iframe and capturing the path as mentioned here.
Then you don't need to deal with exposing a path to load the oidc client lib (oidc-client.min.js or redux-oidc.js) or dumping it's content somewhere.
index.js/ts
import * as React from 'react';
import { render } from 'react-dom';
import { processSilentRenew } from 'redux-oidc';
import App from './App';
if (window.location.pathname === '/silent-renew') {
processSilentRenew();
} else {
render(<App />, document.getElementById('root'));
}
Please note that /silent-renew request performance can be potentially negatively impacted by large files that loaded along with the application. Some thoughts on it in the comment.
I got it to work by simply adding a route instead of using a separat endpoint. My setup is a create-react-app with redux, redux-oidc & react-router.
I configured the UserManager to use
{
silent_redirect_uri: `${window.location.protocol}//${window.location.hostname}${window.location.port ? `:${window.location.port}` : ""}/silent_renew`
}
I added this route in my react-router:
<Route exact={true} path={"/silent_renew"} component={SilentRenewComponent} />
The SilentRenewComponnent is a simple function component which calls the redux-oidc function to process the redirect.
import React from "react";
import { processSilentRenew } from "redux-oidc";
export const SilentRenewComponent = () => {
processSilentRenew();
return(
<div>SilentRenewComponent</div>
);
};
As previously said, changing the webpack configuration of create-react-app would defies what the purpose of this project is, providing a way to do React with zero-configuration.
I'm afraid the solution would be to eject your app, which is irreversible.
After doing so, create the silent_renew directory at the root of your project with the index.js and index.html file, create a store for redux as seen here (you probably don't need a lot of this stuff, like sagas, the router and logger middleware, just take the loadUser logic and store creation), import the store in the src/index.js file and create a redux Provider, like this.
Then, you can modify config/webpack.config.dev.js and follow what we can see at the redux-oihc-example webpack conf. Add HtmlWebpackPlugin and CommonsChunkPlugin for silentRenew, and the additional entry point.
What's a bit upsetting about CRA is that their webpack configuration for dev and prod are totally separated and do not extend a shared one. You'll have to do this operation in both prod and dev configs, or extend one other conf file to prevent redundancy, like this for example.
I would also advice you to use another simple scaffold, CRA is good when you don't have anything special to do unlike what you want (and probably more in the future). Ejecting will create a lot of files and code that you don't even need in your own codebase. A friend and I made a minimalist one, but I'm sure there is plenty of better alternatives.
You cannot add a custom webpack loader if you haven't ejected:
We don't intend to provide Webpack specific overrides because it will be very fragile. People will start depending on specific loaders and plugins and we won't be able to improve the overall experience.
source: https://github.com/facebookincubator/create-react-app/issues/99#issuecomment-234657710
If you want to add a new specific entry file you first need to yarn eject then edit config/webpack.config.dev.js:34 and config/webpack.config.prod.js:55.
The same is valid for adding new webpack loaders.