How to set env.development and env.production in Preact app - preact

On react app, you can create .env.production and .env.development and enter different key and values like this.
REACT_APP_API_URL= "xyz"
to pick environment variables automatically based on commands used --> npm start or npm run build.
What is the equivalent process in preact?

It is my solution
env.js in the root of project:
import fs from 'fs';
import dotenv from 'dotenv';
function getAppEnvironment() {
const prefix = "PREACT";
return Object.keys(process.env)
.filter((key) => new RegExp(`^${prefix}_`, 'i').test(key))
.reduce((env, key) => {
env[key] = process.env[key];
return env;
}, {});
}
function resolveFile(file) {
const path = fs.realpathSync(process.cwd());
return `${path}/${file}`;
}
function getEnvFiles(production) {
const key = production ? 'production' : 'development';
return [
resolveFile(".env"),
resolveFile(".env.local"),
resolveFile(`.env.${key}`),
resolveFile(`.env.${key}.local`),
].filter(Boolean);
}
export function getEnvironment(production) {
const dotenvFiles = getEnvFiles(production);
dotenvFiles.forEach((dotenvFile) => {
if (fs.existsSync(dotenvFile)) {
dotenv.config({
path: dotenvFile,
override: true
})
}
});
return getAppEnvironment();
}
export default getEnvironment;
then create or modify your preact.config.js:
import getEnvironment from './env';
export default {
plugins: [],
webpack(config, env, helpers) {
config.plugins.push(
new helpers.webpack.DefinePlugin({
'process.env': JSON.stringify(getEnvironment(env.production))
}),
);
},
};

Related

how to upgrade webpack from 3 to 5

I really need someone's help.
In this repo,
https://github.com/ueno-llc/starter-kit-universally.git
I don't know how to upgrade the webpack.
The error is from new webpack.NamedChunksPlugin, new webpack.optimize.CommonsChunkPlugin
I can't fix it by myself...
Can anyone help me for this issue ?
import fs from 'fs';
import _isArray from 'lodash/isArray';
import _get from 'lodash/get';
import appRootDir from 'app-root-dir';
import path from 'path';
import webpack from 'webpack';
import ExtractCssChunks from 'extract-css-chunks-webpack-plugin';
import ExtractTextPlugin from 'extract-text-webpack-plugin';
import ChunkManifestWebpackPlugin from 'chunk-manifest-webpack-plugin';
import NameAllModulesPlugin from 'name-all-modules-plugin';
import config from '../';
import { removeNil } from '../../internal/utils/arrays';
import { ifElse } from '../../internal/utils/logic';
function externals() {
// UENO: Define externals
// We don't want our node_modules to be bundled with any bundle that is
// targetting the node environment, prefering them to be resolved via
// native node module system.
// Some of our node_modules may contain files that depend on our
// webpack loaders, e.g. CSS or SASS.
// For these cases please make sure that the file extensions are
// registered within the following configuration setting.
const whitelist = [
/\.bin/,
'source-map-support/register',
'react-universal-component',
'webpack-flush-chunks',
]
// And any items that have been whitelisted in the config need
// to be included in the bundling process too.
.concat(config('nodeExternalsFileTypeWhitelist') || []);
return fs
.readdirSync(path.resolve(appRootDir.get(), 'node_modules'))
.filter(x => !whitelist.some((w) => {
if (w instanceof RegExp) {
return w.test(x);
}
return x === w;
}))
.reduce((ext, mod) => {
// mark this module as external
// https://webpack.js.org/configuration/externals
ext[mod] = `commonjs ${mod}`;
return ext;
}, {});
}
export default (webpackConfig, buildOptions) => {
const { target, optimize = false, localIdentName } = buildOptions;
const isProd = optimize;
const isDev = !isProd;
const isClient = target === 'client';
const isNode = !isClient;
const ifNode = ifElse(isNode);
const ifClient = ifElse(isClient);
const ifProdClient = ifElse(isProd && isClient);
// Overwrite the externals because apparently `webpack-node-externals` does not
// work well with `webpack-flush-chunks`
if (isNode) {
webpackConfig.externals = [externals()];
}
// Remove ExtractTextPlugin
const etpIndex = webpackConfig.plugins.findIndex(p => p instanceof ExtractTextPlugin);
if (etpIndex > -1) {
webpackConfig.plugins.splice(etpIndex, 1);
}
// Add some plugins for css code splitting
webpackConfig.plugins.push(
...removeNil([
// NamedModulesPlugin, NamedChunksPlugin and NameAllModulesPlugin (see below) are all here to
// deal with chunk hashes.
// See https://medium.com/webpack/predictable-long-term-caching-with-webpack-d3eee1d3fa31
ifClient(new webpack.NamedModulesPlugin()),
ifClient(
new webpack.NamedChunksPlugin((chunk) => {
if (chunk.name) {
return chunk.name;
}
return chunk.mapModules(m => path.relative(m.context, m.request)).join('_');
}),
),
ifClient(new ExtractCssChunks({
filename: isDev ? '[name].js' : '[name]-[contenthash].css',
})),
ifProdClient(new ChunkManifestWebpackPlugin({
filename: '../manifest.json',
manifestVariable: '__WEBPACK_MANIFEST__',
})),
// To make sure chunk hashes stay the same if their contents don’t change
// see: https://webpack.js.org/guides/caching/#module-identifiers
ifClient(new webpack.HashedModuleIdsPlugin()),
// Add vendor code chunk
ifProdClient(
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
filename: '[name]-[chunkhash].js',
// Put all node_modules into one chunk
// see: https://webpack.js.org/plugins/commons-chunk-plugin/#passing-the-minchunks-property-a-function
minChunks: module => module.context && module.context.includes('node_modules'),
}),
),
// Add webpack boilerplate chunk
ifClient(
new webpack.optimize.CommonsChunkPlugin({
name: 'bootstrap', // needed to put webpack bootstrap code before chunks
filename: isDev ? '[name].js' : '[name]-[chunkhash].js',
}),
),
ifClient(new NameAllModulesPlugin()),
// We only want one server chunk
ifNode(
new webpack.optimize.LimitChunkCountPlugin({
maxChunks: 1,
}),
),
]),
);
const { rules } = webpackConfig.module;
const moduleRules = [..._get(rules, '0.oneOf', rules)];
// Overwrite css loader ExtractTextPlugin
const cssRule = moduleRules.find(r => r.test.test('.css'));
if (cssRule && _isArray(cssRule.use)) {
// Find plugin
const pluginIndex = cssRule.use.findIndex(u =>
Object.prototype.hasOwnProperty.call(u, 'loader') && /extract-text-webpack-plugin/.test(u.loader));
if (pluginIndex > -1) {
const loaders = ExtractCssChunks.extract({
fallback: 'style-loader',
use: [
`css-loader?modules=1&importLoaders=1&localIdentName=${localIdentName}`,
'postcss-loader',
'sass-loader?outputStyle=expanded',
],
});
cssRule.use.splice(
pluginIndex,
loaders.length,
...loaders,
);
}
}
// Overwrite node_modules css loader ExtractTextPlugin
const nmCssRule = moduleRules.find(r =>
r.test.test('node_modules.css') &&
(!r.exclude || !r.exclude.test('node_modules.css')));
if (nmCssRule && _isArray(nmCssRule.use)) {
// Find plugin
const pluginIndex = nmCssRule.use.findIndex(u =>
Object.prototype.hasOwnProperty.call(u, 'loader') && /extract-text-webpack-plugin/.test(u.loader));
if (pluginIndex > -1) {
const loaders = ExtractCssChunks.extract({
fallback: 'style-loader',
use: ['css-loader', 'postcss-loader'],
});
nmCssRule.use.splice(
pluginIndex,
loaders.length,
...loaders,
);
}
}
return webpackConfig;
};
===
I have tried to use webpack.config.js, but still failed...
Please help me :(

Unable to read values from .env.local file in latest Cypress version

I am using latest Cypress version 10.11.0 and I am trying to read username, password from .env.local file in my system using process.env. But some how it not getting the values from the .env.local file ? Could someone please advise ?
Note : As a normal way, I am able to get values if I provide values in cypress.config.js (see below). Since username, password can't expose in config, i need to read it from .env.local file.
env:{
MYBOOKS_USERNAME:"testuser1#test.com",
MYBOOKS_PASSWORD:"Some_password"
},
// cypress.config.js file
const { defineConfig } = require("cypress");
module.exports = defineConfig({
chromeWebSecurity: false,
viewportWidth :1920,
viewportHeight:1080,
responseTimeout: 60000,
fixturesFolder: 'cypress/fixtures',
screenshotsFolder: 'cypress/screenshots',
videosFolder: 'cypress/videos',
numTestsKeptInMemory: 10,
video:false,
e2e: {
setupNodeEvents(on, config) {
require("cypress-grep/src/plugin")(config),
// implement node event listeners here
on('before:browser:launch', (browser, launchOptions ) => {
console.log("Print browser name: "+browser.name);
if (browser.name === 'chrome' || browser.name === 'chrome' && browser.isHeadless) {
launchOptions.args.push('--disable-features=SameSiteByDefaultCookies')
return launchOptions
}
});
on('task', {
logAtConsole (message) {
console.log('Printing the data using task::', message);
return null
}
});
},
baseUrl: "https://somebookssite-test.com",
specPattern: "cypress/e2e/booksSite/**/*.spec.{js,jsx,ts,tsx}",
},
});
// .env.local file
CYPRESS_MYBOOKS_USERNAME=testuser1#test.com,
CYPRESS_MYBOOKS_PASSWORD=Some_password
// commands.js file
const userName = process.env.MYBOOKS_USERNAME;
const userPassword = process.env.MYBOOKS_PASSWORD;
Cypress.Commands.add('loginRequest', (url) => {
helperFunctions.dynamicEnvironmentSelection();
const apiEndpoint = helperFunctions.getItemFromLocalStorage('apiUrl');
cy.request({
method: 'POST',
url: apiEndpoint + url,
contentType: 'application/json',
body: {
username: userName,
password: userPassword,
}
}).then((resp) => {
helperFunctions.setLoginCookies(resp);
});
});
You could use dotenv to read the .env.local file.
Using the convention for this tool, use key=value format in .env.local.
MYBOOKS_USERNAME="testuser1#test.com"
MYBOOKS_PASSWORD="Some_password"
const { defineConfig } = require('cypress')
const path = require('path')
const dotenv = require('dotenv')
const envLocal = dotenv.config({path: path.resolve(process.cwd(), '.env.local')})
module.exports = defineConfig({
env: {
// non-sensitive env vars hard-coded here
login_url: '/login',
products_url: '/products'
// sensitive env vars read in above from external file
...envLocal
},
Without dotenv
If you change the external file to .env.local.json, then it's possible to read it directly.
{
"MYBOOKS_USERNAME": "testuser1#test.com",
"MYBOOKS_PASSWORD": "Some_password"
}
const { defineConfig } = require('cypress')
const envLocal = require('./.env.local.json')
module.exports = defineConfig({
env: {
// non-sensitive env vars hard-coded here
login_url: '/login',
products_url: '/products'
// sensitive env vars read in above from external file
...envLocal
},

Fastify CLI decorators undefined

I'm using fastify-cli for building my server application.
For testing I want to generate some test JWTs. Therefore I want to use the sign method of the fastify-jwt plugin.
If I run the application with fastify start -l info ./src/app.js everything works as expected and I can access the decorators.
But in the testing setup I get an error that the jwt decorator is undefined. It seems that the decorators are not exposed and I just can't find any error. For the tests I use node-tap with this command: tap \"test/**/*.test.js\" --reporter=list
app.js
import { dirname, join } from 'path'
import autoload from '#fastify/autoload'
import { fileURLToPath } from 'url'
import jwt from '#fastify/jwt'
export const options = {
ignoreTrailingSlash: true,
logger: true
}
export default async (fastify, opts) => {
await fastify.register(jwt, {
secret: process.env.JWT_SECRET
})
// autoload plugins and routes
await fastify.register(autoload, {
dir: join(dirname(fileURLToPath(import.meta.url)), 'plugins'),
options: Object.assign({}, opts),
forceESM: true,
})
await fastify.register(autoload, {
dir: join(dirname(fileURLToPath(import.meta.url)), 'routes'),
options: Object.assign({}, opts),
forceESM: true
})
}
helper.js
import { fileURLToPath } from 'url'
import helper from 'fastify-cli/helper.js'
import path from 'path'
// config for testing
export const config = () => {
return {}
}
export const build = async (t) => {
const argv = [
path.join(path.dirname(fileURLToPath(import.meta.url)), '..', 'src', 'app.js')
]
const app = await helper.build(argv, config())
t.teardown(app.close.bind(app))
return app
}
root.test.js
import { auth, build } from '../helper.js'
import { test } from 'tap'
test('requests the "/" route', async t => {
t.plan(1)
const app = await build(t)
const token = app.jwt.sign({ ... }) //-> jwt is undefined
const res = await app.inject({
method: 'GET',
url: '/'
})
t.equal(res.statusCode, 200, 'returns a status code of 200')
})
The issue is that your application diagram looks like this:
and when you write const app = await build(t) the app variable points to Root Context, but Your app.js contains the jwt decorator.
To solve it, you need just to wrap you app.js file with the fastify-plugin because it breaks the encapsulation:
import fp from 'fastify-plugin'
export default fp(async (fastify, opts) => { ... })
Note: you can visualize this structure by using fastify-overview (and the fastify-overview-ui plugin together:

Vite keeps refreshing the entire page

I migrated from CRA to Vite and it keeps refreshing the entire page.
I saw this issue #7131 on GitHub and that's not my problem.
Here's my vite.config.js:
import { defineConfig, loadEnv } from 'vite'
import react from '#vitejs/plugin-react'
const path = require(`path`)
const aliases = {
'#Form': 'src/Components/Form/Exports',
'#List': 'src/Components/List/Exports',
'#Browse': 'src/Components/Browse/Browse',
'#Tree': 'src/Components/Tree/Exports',
'#Tab': 'src/Components/Tab/Exports',
'#Dashboard': 'src/Components/Dashboard/Dashboard',
'#Panel': 'src/Panel/Panel',
}
const resolvedAliases = Object.fromEntries(
Object.entries(aliases).map(([key, value]) => [key, path.resolve(__dirname, value)]),
)
export default defineConfig(({ mode }) => {
const env = loadEnv(mode, '.')
console.log(env)
const htmlPlugin = () => {
return {
name: "html-transform",
transformIndexHtml(html) {
return html.replace(/%(.*?)%/g, function (match, p1) {
return env[p1]
})
},
}
}
return {
resolve: {
alias: resolvedAliases
},
plugins: [react(), htmlPlugin()],
server: {
host: '0.0.0.0',
hmr: {
clientPort: 443
}
}
}
})
Since my project contains hundreds of components, and it use OAuth and third party authenticators, each reload takes a considerable amount of time (maybe 5 seconds).
This hugely slows down the development.
What should I do to fix this?
What should I do to prevent this?

why I am not able to import lodash in angular2

I am using angular-cli in angular2 rc1 for development.
I have installed lodash node_module through npm and configured it in systemjs using following:
system.config.ts
/***********************************************************************************************
* User Configuration.
**********************************************************************************************/
/** Map relative paths to URLs. */
const map: any = {
};
/** User packages configuration. */
const packages: any = {
};
////////////////////////////////////////////////////////////////////////////////////////////////
/***********************************************************************************************
* Everything underneath this line is managed by the CLI.
**********************************************************************************************/
const barrels: string[] = [
// Angular specific barrels.
'#angular/core',
'#angular/common',
'#angular/compiler',
'#angular/http',
'#angular/router',
'#angular/platform-browser',
'#angular/platform-browser-dynamic',
'ng2-dnd',
'ng2-bootstrap',
'moment',
'lodash',
// Thirdparty barrels.
'rxjs',
// App specific barrels.
'app',
'app/shared',
/** #cli-barrel */
];
const cliSystemConfigPackages: any = {};
barrels.forEach((barrelName: string) => {
if(barrelName=='ng2-dnd'){
cliSystemConfigPackages[barrelName] = { main: 'ng2-dnd' };
}else if (barrelName == 'ng2-bootstrap') {
cliSystemConfigPackages[barrelName] = { main: 'ng2-bootstrap' };
}else if (barrelName == 'lodash') {
cliSystemConfigPackages[barrelName] = { main: 'lodash' };
}else if (barrelName == 'moment') {
cliSystemConfigPackages[barrelName] = { main: 'moment' };
}else{
cliSystemConfigPackages[barrelName] = { main: 'index' };
}
});
/** Type declaration for ambient System. */
declare var System: any;
// Apply the CLI SystemJS configuration.
System.config({
map: {
'#angular': 'vendor/#angular',
'rxjs': 'vendor/rxjs',
'main': 'main.js',
'ng2-dnd': 'vendor/ng2-dnd',
'ng2-bootstrap':'vendor/ng2-bootstrap',
'moment':'vendor/moment',
'lodash':'vendor/lodash'
},
meta: {
lodash: { format: 'amd' }
},
packages: cliSystemConfigPackages
});
// Apply the user's configuration.
System.config({ map, packages });
I would just like to note that other node_modules are working correctly i.e. moment,ng2-bootstrap etc.
angular-cli-build.js
/* global require, module */
var Angular2App = require('angular-cli/lib/broccoli/angular2-app');
module.exports = function(defaults) {
return new Angular2App(defaults, {
vendorNpmFiles: [
'systemjs/dist/system-polyfills.js',
'systemjs/dist/system.src.js',
'zone.js/dist/**/*.+(js|js.map)',
'es6-shim/es6-shim.js',
'reflect-metadata/**/*.+(js|js.map)',
'rxjs/**/*.+(js|js.map)',
'#angular/**/*.+(js|js.map)',
'ng2-dnd/**/*.js',
'ng2-bootstrap/**/*.js',
'moment/*.js',
'lodash/*.js'
]
});
};
after this configuration of lodash node_module, I am importing it from the directory dist\vendors\lodash
in my app.component i am importing it as :
import _ from 'lodash';
But I am getting below error:
Cannot find module 'lodash'
any solutions?
thanks in advance
I can suggest you a workaround until they get better support for 3rd party libs. It worked for me :)
In your angular-cli-build.json , make sure it remains like this way
module.exports = function(defaults) {
return new Angular2App(defaults, {
vendorNpmFiles: [
...
'lodash/**/*.js'
]
});
};
and in your system-config.ts:
/** Map relative paths to URLs. */
const map: any = {
'lodash': 'vendor/lodash/lodash.js'
};
/** User packages configuration. */
const packages: any = {
'lodash': {
format: 'cjs'
}
};
in your src/index.html add this line
<script src="/vendor/lodash/lodash.js" type="text/javascript"></script>
now in your component where you want to use lodash , write this way
declare var _:any;
#Component({
})
export class YourComponent {
ngOnInit() {
console.log(_.chunk(['a', 'b', 'c', 'd'], 2));
}
}
Try using:
import * as _ from 'lodash';

Resources