How can I use Vite env variables in vite.config.js? - javascript

With the following .env in my Vite project:
# To prevent accidentally leaking env variables to the client, only
# variables prefixed with VITE_ are exposed to your Vite-processed code
VITE_NAME=Wheatgrass
VITE_PORT=8080
How can I use VITE_PORT in my vite.config.js?

You can load the app level env variables and add them to the Node level env variables:
import { defineConfig, loadEnv } from 'vite';
import vue from '#vitejs/plugin-vue';
export default ({ mode }) => {
process.env = {...process.env, ...loadEnv(mode, process.cwd())};
// import.meta.env.VITE_NAME available here with: process.env.VITE_NAME
// import.meta.env.VITE_PORT available here with: process.env.VITE_PORT
return defineConfig({
plugins: [vue()],
server: {
port: parseInt(process.env.VITE_PORT),
},
});
}

If the above solution by #matt doesnt work for you then change the vite.config.ts/ vite.config.js like below
1st Solution
import { defineConfig, loadEnv } from 'vite';
import vue from '#vitejs/plugin-vue';
export default defineConfig(({ mode }) => {
const env = loadEnv(
'mock',
process.cwd(),
''
)
const processEnvValues = {
'process.env': Object.entries(env).reduce(
(prev, [key, val]) => {
return {
...prev,
[key]: val,
}
},
{},
)
}
return {
plugins: [vue()],
define: processEnvValues
}
}
2nd Solution
import { defineConfig, loadEnv } from 'vite';
import vue from '#vitejs/plugin-vue';
export default ({ mode }) => {
process.env = Object.assign(process.env, loadEnv(mode, process.cwd(), ''));
return defineConfig({
plugins: [vue()],
});
}

Related

Problems with Amplify and Vite

I am getting errors while setting up Amplify Authentication with React and Vite.
This is what I have tried already.
Packages used:
"#aws-amplify/ui-react": 4.2.0
"aws-amplify": 5.0.5
Main.jsx
import Amplify from "aws-amplify"
import awsExports from "./aws-exports"
Amplify.configure(awsExports)
vite.config.js
import { defineConfig } from 'vite'
import postcss from './postcss.config.js'
import react from '#vitejs/plugin-react'
// https://vitejs.dev/config/
export default defineConfig({
define: {
'process.env': process.env,
'global': {}
},
css: {
postcss,
},
plugins: [react()],
resolve: {
alias: [
{
find: /^~.+/,
replacement: (val) => {
return val.replace(/^~/, "");
},
},
{
find: './runtimeConfig', replacement: './runtimeConfig.browser',
}
],
},
build: {
commonjsOptions: {
transformMixedEsModules: true,
}
}
})
Running, npm run dev, app crashes and console has this error:
'Uncaught SyntaxError: The requested module '/node_modules/.vite/aws-amplify.js?v=d4f24853' does not provide an export named 'default' (at main.jsx:5:1)'

How do Vite MPAs using the Vue plugin work?

I have a Vite app created and I need it to have multiple pages. I read the docs and found how to do this (can be found here), however when I run the server I get a blank page.
My vite.config.js file:
import { defineConfig } from 'vite'
import vue from '#vitejs/plugin-vue'
const { resolve } = require('path')
module.exports = {
build: {
rollupOptions: {
input: {
home: resolve(__dirname, 'src/Home/index.html')
}
}
}
}
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()]
})
Here's what my file structure looks like:
Edit: I have changed the config to what tony posted below, but it is still showing a blank page.
Edit 2: I found out that you don't need to use the vite.config.js routing, there's an easier way
Create a copy of your main.js, App.vue, and index.html file and rename them to something different. After you rename them change the <script type="module" src="index.js"></script> to your new JS file, and change the .vue file import in your new main.js to your new .vue file. Here's my new structure:
All I did was copy the files and change the names and imports, and it worked!
You have two default exports in vite.config.js, but there should only be one:
module.exports = { 1️⃣
//...
}
export default defineConfig({ 2️⃣
//...
})
The config should be:
import { defineConfig } from 'vite'
import vue from '#vitejs/plugin-vue'
import { resolve } from 'path'
export default defineConfig({
plugins: [vue()],
build: {
rollupOptions: {
input: {
home: resolve(__dirname, 'src/Home/index.html')
}
}
}
})
GitHub demo

Import JSX file into webpack config

I am trying to import a JSX file into my webpack config. It appears the file imports, but I cannot import modules into that file. I continuously get an error saying Cannot use import statement outside a module
Here is my webpack.config.js:
const bodyParser = require('body-parser')
require('#babel/register')
const render = require('../src/static/render.jsx')
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const path = require('path');
const PATHS = {
app: path.join(__dirname, '../src/static'),
build: path.join(__dirname, '../src/static_dist')
};
const basePath = path.resolve(__dirname, '../src/static/');
module.exports = {
mode: 'development',
devtool: 'cheap-module-eval-source-map',
output: {
filename: '[name].js',
path: PATHS.build,
publicPath: '/static/'
},
devServer: {
before: function(app) {
app.use(bodyParser.json({ limit: '10mb' }))
app.post('/render', function (req, res) {
res.sendStatus(204);
const initialState = {} //buildInitialState(req.body)
const result = render(url, initialState)
res.json({
html: result.html,
finalState: result.finalState
})
});
},
// Render.jsx
require('#babel/register');
import React from 'react' <-- error happens here
import { Provider } from 'react-redux'
import { match, RouterContext } from 'react-router'
import ReactDOMServer from 'react-dom/server'
import configureStore from './store/configureStore';
import { createBrowserHistory } from "history";
import { routes } from "../routes.js";
import AdminNavbar from "./components/Navbars/AdminNavbar.jsx";
import Sidebar from "./components/Sidebar/Sidebar.jsx";
export default function render (url, initialState) {
... a function ...
}
I feel like I have tried everything! Tinkering with babel, adding #babel/register, adding a .babelrc, changing how it is imported, etc.
You likely need to tell Webpack to resolve that particular extension.
Here's the documentation on resolve: Resolve
The code:
module.exports = {
//...
resolve: {
extensions: ['.js', '.jsx']
}
};
Also I notice you haven't specified your entry. If the solution above doesn't work, try specifying the following:
module.exports = {
//...
entry: './src/Render.jsx'
};
Docs: Entry Point
You likely have to do both.

How can I use a class that use conditional export in Angular's app.module?

This question is the beggining of the story if you want to understand it deeper.
I'm trying to use this class in app.module:
import { Injectable } from '#angular/core';
import { KeycloakService } from 'keycloak-angular';
import { environment } from '../../../environments/environment';
#Injectable({ providedIn: 'root' })
export class MockKeycloakService {
init(ign: any) {
console.log('[KEYCLOAK] Mocked Keycloak call');
return Promise.resolve(true);
}
getKeycloakInstance() {
return {
loadUserInfo: () => {
let callback;
Promise.resolve().then(() => {
callback({
username: '111111111-11',
name: 'Whatever Something de Paula',
email: 'whatever#gmail.com',
});
});
return { success: (fn) => callback = fn };
}
} as any;
}
login() {}
logout() {}
}
const exportKeycloak =
environment.production ? KeycloakService : MockKeycloakService;
export default exportKeycloak;
This conditional export fakes keycloak call to use in local development and returns the real class in production.
This is the app.module I used:
<...>
import { KeycloakAngularModule } from 'keycloak-angular';
import KeycloakService from './shared/services/keycloak-mock.service';
import { initializer } from './app-init';
<...>
imports: [
KeycloakAngularModule,
<...>
],
providers: [
<...>,
{
provide: APP_INITIALIZER,
useFactory: initializer,
multi: true,
deps: [KeycloakService, <...>]
},
<...>
],
bootstrap: [AppComponent]
})
export class AppModule { }
related app-init:
import KeycloakService from './shared/services/keycloak.mock.service';
import { KeycloakUser } from './shared/models/keycloakUser';
import { environment } from '../environments/environment';
<...>
export function initializer(
keycloak: any,
<...>
): () => Promise<any> {
return (): Promise<any> => {
return new Promise(async (res, rej) => {
<...>
await keycloak.init({
<...>
}).then((authenticated: boolean) => {
if (!authenticated) return;
keycloak
.getKeycloakInstance()
.loadUserInfo()
.success(async (user: KeycloakUser) => {
<...>
})
}).catch((err: any) => rej(err));
res();
});
};
All works fine in the development mode. I can use the mocked call, and if I enable production in environment.config it makes the real call.
But when I try to build it to publish in production server I get the following error:
ERROR in Can't resolve all parameters for ɵ1 in /vagrant/frontend/src/app/app.module.ts: (?, [object Object], [object Object]).
My guess is that the builder task can't understand the conditional export in the mocked class to use in app.module.
So this forced me to use both classes in the app-init and other class I use it and check for the environment mode in every one. I think it would be a much better solution if I could use only one class to treat this and just import it in all places I need.
this is my build command:
ng build --prod=true --configuration=production --delete-output-path --output-path=dist/
How can I overcome this error in the build ? Also... why on earth all works well in dev mode and the build behaves differently ?
I guess you're using Angular 8 or less.
AOT compiler in those versions doesn't support resolving reference to default export.
So you should be more specific:
keycloak-mock.service.ts
const KeycloakServiceImpl =
environment.production ? KeycloakService : MockKeycloakService;
export { KeycloakServiceImpl };
app.module.ts
import { KeycloakServiceImpl } from './keycloak-mock.service';
...
deps: [KeycloakServiceImpl]
Tip:
ng build --prod is an equivalent of ng build --prod=true --configuration=production

Default export works on the development site, but returns undefined in Storybook

So I'm building some component stubs for a new project I'm making. To see the visuals for these components I'm using Storybook. I have two separate webpack configs for the Storybook build and the regular build. Both inherit from a base config, shown below (I've removed some irrelevant loaders to make reading easier):
const path = require('path')
const config = {
output: {
filename: '[name].js',
path: path.join(__dirname, 'public/js')
},
module: {
rules: [
{
test: /\.jsx?$/,
loader: 'babel-loader',
exclude: /node_modules/,
query: {
presets: ['es2015', 'react'],
plugins: [
'transform-object-rest-spread',
'transform-es2015-destructuring',
["react-css-modules", {
"filetypes": {
".scss": {
"syntax": "postcss-scss",
"plugins": ["postcss-nested"]
}
},
"generateScopedName": "[local]_[hash:base64:5]"
}]
]
}
}
]
},
resolve: {
modules: ['node_modules', path.join(__dirname, 'resources/assets/js')],
}
}
module.exports = config
My Storybook config and my regular config differ like this:
Webpack.config.js
const path = require('path')
const webpack = require('webpack')
const UglifyJSPlugin = require('uglifyjs-webpack-plugin')
const webpackBaseConfig = require(path.join(__dirname, 'webpack.base.config.js'))
const plugins = [
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: Infinity,
}),
]
if(process.env.NODE_ENV === 'production') {
plugins.push(new UglifyJSPlugin())
}
const webpackConfig = Object.assign(webpackBaseConfig, {
entry: {
vendor: ['react', 'react-dom', 'react-redux', 'react-router', 'react-router-dom', 'redux-form', 'axios', 'redux'],
app: path.join(__dirname, 'resources/assets/js/app.jsx'),
},
plugins,
})
module.exports = webpackBaseConfig
Webpack.storybook.config.js
const path = require('path')
const webpackBaseConfig = require(path.join(__dirname, '../webpack.base.config.js'))
const storyBookConfig = Object.assign(webpackBaseConfig, {
entry: path.join(__dirname, '../resources/assets/js/app.jsx'),
})
module.exports = storyBookConfig
Now everything works fine when I use the normal build, but when I visit storybook these components seems to break it:
components/AppHeader/AppHeader.component.jsx
import React from 'react'
import { Logo, UserCard } from 'components'
import './AppHeader.scss'
const AppHeader = (props) => {
const { user } = props
return (<div styleName="app-header">
<Logo />
<span styleName="user-profile">
<UserCard firstName={user.firstName} lastName={user.lastName} />
</span>
</div>)
}
export default AppHeader
components/AppHeader/AppHeader.container.jsx
import { connect } from 'react-redux'
import AppHeader from './AppHeader.component.jsx'
const mapStateToProps = (state) => ({
user: state.currentUser,
})
export default connect(
mapStateToProps
)(AppHeader)
The error I get is when exporting the connected component in AppHeader.container.jsx:
Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in.
So it seems as if the default export in AppHeader.component.jsx is undefined? This is what makes me think that it's a problem with the webpack configuration for Storybook, because the container/component combo works when I view it not in Storybook.
Any suggestions/help would be greatly appreciated, thank you :)

Categories

Resources