I'm currently creating a vue app and wondering how to integrate it into a template and passing vars (props) into it.
So I basically run npm run dev, coding the app and all its components and so far everything is fine.
When I run npm run build I'll get some js in my build folder, created by webpack.
I guess (as seen before before here on stackoverflow) I can just load these files in my template, create an html-element mit the id "App" and everything works and the app initializes itself automatically.
But now my problem is: the app fires some Ajax requests, and depending on the environment the targets are different (dev: api.local, test: api.testsystem.com, prod: api.livesystem.com, ...).
And therefore I need to pass the url from outside into the app.
We don't build the app at deployment, as it's on a different repository than the "websites" using it. (Our plans are wether to copy the build files manually in these projects or offer an cdn-like url where the other projects load it). And with other projects I mean a symfony based website, or a typo3 plugin, ...
So, from React I remember you can initiate an app like React.render('app.js', {props: 'api-url': 'http://api.local'}); (don't kill me, it was somehow like this...)
How do I do it in vue?
Like:
new Vue(
<template>
<App :api-url="api-url" />
</template>
<script>
import App from "path/to/app.js";
export default {
data() {
api-url: "inject url here"
}
}
</script>
);
or add an data attribute like <div id="App" data-api-url="http://url"> and try to access it inside the app?
I've also seen something like an env-loader - but I'm not sure if this helps in my case.
You talk about different environment mode. You should read this documentation about how to start vue app with different env mode.
You can define different .env files for each mode and populate process.env with this file, or you can start vue.js with NODE_ENV=development per example, and check for process.env.NODE_ENV where you need to pass appropriate variables.
Related
I'm trying to build my Next.js project but it keeps giving me this error in the terminal:
Error: Build optimization failed: found page without a React Component as default export in
pages/components/context/Context
That's the React context API file, there isn't supposed to be any default export there. Is this a bug or what?
You should move your components outside the pages folder. pages/ should only be used for page components as Next.js routing is based on its structure.
Next.js has a file-system based router built on the concept of pages.
When a file is added to the pages directory it's automatically available as a route.
By default, Next.js assumes anything under the pages folder is a page component and will try to build each file as a page.
Even though the above is the default behaviour, you can configure your Next.js app to include non-page files in the pages directory.
To do so, you can modify the pageExtensions entry in the next.config.js file as shown below. Then rename your page components to have a file extension that includes .page (_document.page.js, _app.page.js, index.page.js, etc).
module.exports = {
pageExtensions: ['page.tsx', 'page.ts', 'page.jsx', 'page.js']
}
With this configuration, Next.js will ignore any file that doesn't contain .page for the purpose of building pages/API routes and routing.
In my case, I had an empty file index.js in a folder. Using Nextjs Default Router
It seems to be not declared default export keyword in context component.
Try it as follow:
const Context = ()=>{
...
}
export default Context
I had the same error.
If you comment out all other code but leave this NextJS won't get mad at you:
export default function Home1() {
return <>{/* nothing */}</>;
}
I like to keep older index files and components locally and on github so this is a nice hack. I just copy all of the existing code add it to a new file and then add 1 to it for example:
index1.js
You can also leave a comment to kind of bring you and other devs up to speed as to why you did this for example:
//good for history of index implementation and associated syntax logic
My task is to introduce library to existing create react app based application.
This library need to be build to separate chunk and should not contain any contenthash in name. Ideally should be build to buildDir/js/widget.js and that is.
Currently all my ts are compiled to js during build and are served with contenthash in name.
I don't know how to build widget.js from src/widget/index.ts because entry point is src/index.ts and it never catch src/widget/index.ts because it is not imported anywhere in main entry point.
This widget.js later will be imported in thirdparty web apps via <script> tag and it will be used to initialize some library like MyLibrary.init(...) so I think webpack should also have some info so this one widget.js should export its methods in special way to the browser during importing external script.
What is best way to get this build proces to work. Also it could be really nice to have it also during development with hot updates.
I don't want contenthash in resulting buildDir/js/widget.js because I don't want to ask my customers every time I have new version to update their <script src="..."> for new file name.
Should I eject this CRA? I'm not sure even if I add another entry point that I will be able to control output file name for one entry point as it is and for another without contenthash.
Or maybe it will be better to create separate webpack config (next to unejected CRA) for this widget but then how to run everything in development mode with hot updates?
I'm using webpack 4.42.0 here in this project.
for your case maybe you need this:
https://dev.to/zhiyueyi/include-your-react-widgets-in-any-web-page-emj
https://github.com/ZhiyueYi/demo-react-web-widget
I want to bundle a vue app with the styles and everything into a single UMD javascript module using vue-cli-service so that I can import it into another Vue app via my component distribution server. I am able to do this with one component on the serve, but I don't know how I'll be able to bundle an entire app and load it remotely into a separate app. I use this article as a guide https://markus.oberlehner.net/blog/distributed-vue-applications-loading-components-via-http/
This is where I am importing it:
{
path: '/games',
component: GamesHome,
children: [
{
path: 'fun',
component: () =>
externalComponent(
'http://localhost:8200/game/Game.cd590421a6d6835e7ae2.umd.min.js'
),
name: 'Fun Game'
}
] }
So basically how do I create a Vue app then bundle it entirely with CSS and all using vue-cli-service
This is the problem which I have been trying to solve from day 1 ever since I started using VueJS. I will not consider a client side JS framework if it does not provide a solution for this problem.
I recently did a PoC in this and able to consume a VueJS application as module in another VueJS application. In my case I have a suite of VueJs applications where each of these applications is running in its own dedicated docker container. These applications have a lot of functionality which is common across all the applications. So I decided to move this common code (page layout, css frameworks etc) to a separate VueJS application and consume all existing VueJS applications as modules in this global application. I call this micro-app based architecture to differentiate it from micro-frontends based architecture because it does not use multiple client side JS frameworks and does not require another framework to achieve this. This is how the deployment architecture looks like in my case (you can ignore kubernetes specific stuff if your are not aware about it) -
Coming back to implementation part, you need to take a step wise approach to convert a VueJS application to a micro-app.
Lets say you project structure look as following (it shows only few files which require changes and NOT all the files) -
app-1
public
index.html
src
main.js
App.vue
router
index.js
store
index.js
Split your vuex state and routes files into global and application specific files -
app-1
public
index.html
src
main.js
App.vue
router
app1
index.js
index.js
store
app1
index.js
index.js
Make a copy of this project (global-app), remove global-app specific files from app-1 and app-1 from specific files from global-app. Also remove index.html and App.vue from app-1 project -
Add ROUTES and STORE_MODULES variables to index.html file of global-app -
<head>
....
....
<script type="text/javascript">
const ROUTES = []
const STORE_MODULES = {}
</script>
</head>
<body>
....
....
<div id="app"></div>
<script type="text/javascript" src="/app1/micro-app.umd.min.js"></script>
<!-- built files will be auto injected -->
</body>
Update router\index.js file of global-app for ROUTES variable -
const routes = [
....
....
]
routes.push(...ROUTES)
const router = new VueRouter({
Update store\index.js file of global-app for STORE_MODULES variable -
export default new Vuex.Store({
....
....
modules: STORE_MODULES
})
Clear content of app-1\src\main.js file and replace it with following content -
import routes from '#/router/app1'
import app1 from '#/store/app1'
ROUTES.push(...routes)
STORE_MODULES['app1'] = app1
Define build-app command under scripts block of package.json file of app-1 -
....
"scripts": {
"build-app": "vue-cli-service build --target lib --formats umd-min --no-clean --name micro-app src/main.js"
},
....
Now build and deploy these two applications in their dedicated containers and update nginx conf file of proxy container to forward requests to these containers as following -
location / {
proxy_pass http://global-app:80;
}
location /app1/ {
proxy_pass http://app1:80/;
}
You can access global app by using IP address and port of nginx container.
I hope I have included all the steps which are required to implement micro-app based architecture. You can refer following git repositories which were created as part of this PoC -
https://github.com/mechcloud/large-app-docker
https://github.com/mechcloud/large-app
https://github.com/mechcloud/large-app-plugin1
While I am not an expert in the internals of client side JS frameworks, I believe this approach will work for other JS frameworks (Angular, React etc) as well.
I have a react component which in development will redirect to a localhost url but in production to a different url. In my backend I have the same situation and there i solved it with a package called dotenv. I was wondering how someone would do this in a react front-end.
export default withRouter(function Login(props) {
useEffect(() => {
if(localStorage.getItem('jwt')){
props.history.push('/dashboard');
}
})
const handleLogin = () => {
window.location.href = "http://localhost:8000/auth/google";
}
return (
<LoginView handleLogin={handleLogin}/>
)
})
You can use dotenv to add environment variables to react as well. During app deployment(in the build process) the environment variables must be replaced with the corresponding URLs (as this is the most frequently encountered use case in front-end applications). This can be done while configuring the build process.
Here is an example using Webpack https://medium.com/#trekinbami/using-environment-variables-in-react-6b0a99d83cf5
The whole idea here is to create a file (called just .env) filled with
your environment variables. To prevent people from finding out your
local database password is the same one you use for every single one
of your accounts on the internet , I urge you to add the .env file to
your .gitignore. Your front-end code will refer to the same
environment variable (process.env.API_URL) on both environments
(development/production), but because you defined different values in
your .env files, the compiled values will be different.
I would suggest having a separate .env file for the react app as it should not be accidentally served with the website.
Create React App has a module(built around the node dotenv module) you can use for adding custom environment variables
https://create-react-app.dev/docs/adding-custom-environment-variables/
The environment variables are embedded during the build time. Since
Create React App produces a static HTML/CSS/JS bundle, it can’t
possibly read them at runtime. To read them at runtime, you would need
to load HTML into memory on the server and replace placeholders in
runtime, as described here. Alternatively you can rebuild the app on
the server anytime you change them.
Its depend on how you are using react.
If you are using react-script, you can go will above solution(https://create-react-app.dev/docs/adding-custom-environment-variables/).
But if you are using webpack, try to use DotenvPlugin in place of dotenv module (https://webpack.js.org/plugins/environment-plugin/).
In my opinion, pls don't follow method 1 use in medium link, as env should not be push on git but package.json need to be done.
i had build react app web page
with custom environment variables
the problem is when i build the script
and change the .env variables no thing change in the website !
.env file :
REACT_APP_SITENAME=TheSiteName App
After building a react app all code is static and can't be changed. I think the only solution to send some dynamic data to your react app is to either create a special file per system you running your app on and load this directly inside the index.html or create the content of this file on the fly.
So when you're using create-react-app in public/index.html add something like this:
<head>
...
<script src="https://www.example.com/envconfig.js" type="text/javascript">
</script>
...
</head>
This file should contain the environmental config, e.g.:
window.globalConfig = {
siteName: "The Sitename App"
}
The file can also be created on the fly by PHP, Java or any other backend service. Just make sure to answer as valid Javascript.
And in your React app at index.js, App.js or anywhere you can access this variable as it is global:
const appConfig = window.globalConfig || { siteName: process.env.REACT_APP_SITENAME}
With this you've got an fallback to the static env config if globalConfig is not available, likely in development.
Now you can use appConfig in any way and provide it via redux, context or property to your components.
Last thing to mention, you have to make sure that the config-file is loaded before executing all the React code. So the file should be loaded before all the created React files.
Quote from the docs:
The environment variables are embedded during the build time.
It isn't possible to apply environment changes as runtime.
Reference
Here is an example of how to use the environment at runtime:
CodeSandbox
here is an idea:
add a json file (e.a. config.json) with your configuration to the "public" folder. That file will be in the root of the build:
{
"name": "value" }
in your React code, create a static class with the variable you want to configure:
class Config {
static name= "[default value overwritten by the config]"; }
somewhere high in the startup of your React application, read the json and set the static variable:
fetch("config.json") .then((r) => r.json()) .then((data) =>{
Config.name=data.name; })
now you can use that config anywhere you need it :
Config.name
Note that any configuration you make will be vulnerable for public eyes, since the file can be opened directly with a URL. Also note that when deleting that json file, everything will still work with the default value. You could implement some check that the file must exist.