HMR in asp.net core with React - asp.net

I started my project using .net core cli.
dotnet new react -o my app
and for development, I changed my env var
export ASPNETCORE_Environment=Development
I am not very comfortable with Typescript so, I prefer use .jsx files and babel, so I decided to change my webpack.config.js. In module rules, I added:
const BABEL_LOADER_PLUGINS = [
require.resolve("babel-plugin-transform-class-properties"),
require.resolve("babel-plugin-transform-object-rest-spread"),
require.resolve("babel-plugin-transform-regenerator")
];
/*...webpack config code ... */
{
test: /\.jsx$/,
exclude: /node_modules/,
use: [
{
loader: "babel-loader",
options: {
presets: ["env", "react"],
plugins: BABEL_LOADER_PLUGINS
}
}
]
}
I did my new components with .jsx extensions and it works. So my next step is to do HMR work.
In my Startup.cs:
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseWebpackDevMiddleware(new WebpackDevMiddlewareOptions
{
HotModuleReplacement = true
});
}
In client at root component, using react-hot-loader':
let HotApp;
if (__CONFIGS__.isDevServer) {
const { hot } = require('react-hot-loader');
HotApp = hot(module)(App);
} else {
HotApp = App;
}
const Root = (
<Provider store={store}>
<BrowserRouter>
<HotApp />
</BrowserRouter>
</Provider>
);
hydrate(Root, document.getElementById('react-app'));
And this sometimes works. In the console, I can see [HMR] connected and updates. If I stop the process, it is possible that console shows [HMR] connected but if I do some changes in a component nothing happens. I don't know why sometimes works well.

We can use Create React App Configuration Override (#craco/craco) along with craco-plugin-react-hot-reload CRACO plugin to add HMR without ejecting the CRA application.
Install #craco/craco by following the installation guide
Install craco-plugin-react-hot-reload
npm i -D craco-plugin-react-hot-reload
Add craco-plugin-react-hot-reload into craco.config.js
const reactHotReloadPlugin = require('craco-plugin-react-hot-reload');
module.exports = {
plugins: [{
plugin: reactHotReloadPlugin
}],
webpack: [...]
}
Install #hot-loader/react-dom
npm i #hot-loader/react-dom
Mark your App component as hot-exported (into ClientApp\src\App.js)
import { hot } from 'react-hot-loader/root';
function App() {...}
export default hot(App);
Now HMR will work properly when we start the project using dotnet run.
Tested (on May 2020) using React 16.13.1. We must use the same major and minor versions for react, react-dom and #hot-loader/react-dom (16.13.x).

Related

How can I get Vite env variables?

I am using Quasar, Vue 3, Vite, Cypress in my project. I don't know how to get .env variables (e.g. VITE_API_URL) and to set in cypress.env.json. Before Vite I used webpack and I know how to do it.
I don't want to define twice same variable, first in .env then in cypress.env.json.
You can use the dotenv package directly, merging the result in with the env section of your cypress config.
.env
VITE_API_URL: "http://example.com"
cypress.config.js
const { defineConfig } = require("cypress");
const dotenv = require('dotenv')
const env = dotenv.config('./.env').parsed
module.exports = defineConfig({
'component': {
// component config here
},
env: {
login_url: '/login',
...env, // merge here with spread operator
},
});
Settings page in the Cypress runner
env: {
login_url: '/login',
VITE_API_URL: 'http://example.com',
},
There is a plugin called cypress-dotenv for this very purpose. It allows you to share your .env file variables between your app and cypress tests.
Install
npm install --save-dev cypress-dotenv
# For typescript
npm install --save-dev #types/cypress-dotenv
Example
Example .env file
VITE_API_URL=https://vite-api-url.com
In your cypress.config.js, run the plugin dotenvCypress() under setupNodeEvents():
import { defineConfig } from "cypress";
import dotenvCypress from 'cypress-dotenv';
export default defineConfig({
component: {
devServer: {
framework: "vue",
bundler: "vite",
},
setupNodeEvents(on, config) {
return dotenvCypress(config, undefined, true);
},
},
});
Then in your test:
it('works', () => {
cy.log(Cypress.env('VITE_API_URL'));
});
Notes
dotenvCypress() must be returned in setupNodeEvents()
To get all the env variables from your .env file, you have to pass true as the third argument to dotenvCypress(). Otherwise, only vars prefixed with CYPRESS_ will be available.
https://www.npmjs.com/package/cypress-dotenv

Uncaught ReferenceError: Buffer is not defined when executing `histoire preview` script in svelte/kit environment

I am new to SvelteKit and Vite. I love the work of Histoire ! (storybook alternative for vue and svelte)
Unfortunately I encounter an issue when trying to preview the histoire build...
Preview (histoire preview) is rendering a blank page with the following console error: Uncaught ReferenceError: Buffer is not defined coming from vendor file.
I already tried to search answers in Histoire Github existing issues section with no success. It seems like I am the only one facing this issue so I probably missing something but I don't know where. Missing config in histoire.config, svelte.config or vite.config ? Issue with deps versions ?
here some details about my environment:
// package.json
{
...
"scripts": {
...
"story:dev": "histoire dev",
"story:build": "histoire build",
"story:preview": "histoire preview"
},
"devDependencies": {
...
"#histoire/plugin-svelte": "^0.13.0",
"#sveltejs/adapter-auto": "^1.0.3",
"#sveltejs/kit": "^1.5.0",
"histoire": "^0.13.0",
"svelte": "^3.55.1",
"svelte-check": "^3.0.3",
"typescript": "^4.9.5",
"vite": "^4.1.1",
...
},
"type": "module",
...
}
I also tried to downgrade histoire to the 0.12.* without any success.
// histoire.confg.ts
import { defineConfig } from 'histoire';
import { HstSvelte } from '#histoire/plugin-svelte';
export default defineConfig({
setupFile: '/src/histoire-setup.ts',
plugins: [HstSvelte()]
});
I know that I can override the vite config of my histoire config. I tried adding an alias for Buffer and other stuff but nothing seems to work.
// svelte.config.cjs
import adapter from '#sveltejs/adapter-auto';
import { vitePreprocess } from '#sveltejs/kit/vite';
/** #type {import('#sveltejs/kit').Config} */
const config = {
preprocess: vitePreprocess(),
kit: {
adapter: adapter()
}
};
export default config;
// vite.config.ts
import { sveltekit } from '#sveltejs/kit/vite';
import type { UserConfig } from 'vite';
const config: UserConfig = {
plugins: [sveltekit()],
};
export default config;
Like I said I tried multiple things to resolve this issue:
Downgrade Histoire version to 0.12.*
Override vite config of histoire.config.ts file by adding a Buffer alias and installing it as a deps
I also tried to install node-stdlib-browser following this issue answer
But nothing works as expected.

Firebase Cloud Messaging SW integration with Svelte-Kit

Has anyone integrated Firebase Cloud Messaging with Svelte-Kit. My main issue is registering the firebase-messaging-sw.js. If placed in the static directory I get a 'Syntax Error for using import outside of a module'. I've tried adding the file to the src directory, and telling vite about it. My svelte.config.js looks like this.
import adapter from '#sveltejs/adapter-node';
import preprocess from 'svelte-preprocess';
/** #type {import('#sveltejs/kit').Config} */
const config = {
preprocess: preprocess(),
kit: {
adapter: adapter({
out: 'dist'
}),
csrf: {
checkOrigin: false,
},
files: {
serviceWorker: 'src/firebase-messaging-sw.js'
}
},
};
export default config;
I am testing using vite build && vite preview with no luck. I feel like i'm missing a simple config to keep the file at the root of the project.
The solution I found was to use 'importScripts' a service worker helper I wasn't aware of.
importScripts('https://www.gstatic.com/firebasejs/9.10.0/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/9.10.0/firebase-messaging.js');

Disable es5 transpilation while developing in nextjs

Is there a way to disable transpilation of es5 code (such as async functions) while in next dev?
Setting the babel preset-env does not work, and this previous answer no longer works either.
Setting the browserlist target within package.json still transpiles the code as well
As of Jan 2023 I found a few flags that help get you most of the way there.
const isProd = process.env.NODE_ENV === "production";
const nextConfig = {
webpack: (config, { dev }) => {
if (dev && Array.isArray(config.target) && config.target.includes('web')) {
config.optimization.minimize = false;
delete config.optimization.minimizer;
config.target = ["web", "es2020"];
}
return config;
}
};
if (!isProd) {
nextConfig.experimental = {
legacyBrowsers: false,
};
}
module.exports = nextConfig;
This will disable legacy browser support and use your browser list for swc, and then also changes the targets for webpack. Doesn't completely remove transpilation but it's way better than the default
Also, nextjs now supports browserslist in your package.json - source
Adding the following key to your package.json will enable most features by default:
{
"browserslist": [
"chrome 109"
]
}

How to use TS Path Mapping with Firebase Cloud Functions

How do I use TS Path Mapping with Firebase Cloud Functions?
I tried without success:
"baseUrl": ".",
"paths": {
"#custom-path/*": ["src/utils/*"],
"#other-path/*": ["../other/path/*"]
}
Finally I was able to do this with module-alias NPM package.
Install it as non-dev dependency: yarn add module-alias #types/module-alias
Create a file fixTsPaths.ts or whatever with content like this:
import * as ModuleAlias from 'module-alias';
ModuleAlias.addAliases({
'common': __dirname + '/../../../common',
});
Here's the trick about the path /../../../common: in my case this folder is outside functions, and Typescript replicates folders structure during the build, so that's could be the reason why https://github.com/dividab/tsconfig-paths was not working out of the box. So in every case one needs to check this path and find appropriate '..' count :)
And finally import this file in your index.ts at the very top:
import './fixTsPaths';
Hope this helps!
It's 2022 and the neatest way to do this is to use tsc-alias.
On tsconfig.json, add baseUrl and add your paths under compilerOptions. Something like:
{
"compilerOptions": {
...
"baseUrl": "./src",
"paths": {
"#constants/*": ["api/constants/*"],
"#interfaces/*": ["api/interfaces/*"],
"#middlewares/*": ["api/middlewares/*"],
"#modules/*": ["api/modules/*"],
"#services/*": ["api/services/*"]
},
...
}
Then, change your serve and build scripts, under package.json. Like:
...
"scripts": {
"build": "tsc && tsc-alias",
"build:watch": "concurrently \"tsc -w\" \"tsc-alias -w\"",
"serve": "concurrently --kill-others \"firebase emulators:start --only functions\" \"npm run build:watch\"",
...
},
...
☝️ here I'm using concurrently, but feel free to use whatever you like.
And that's it. You can now import stuff using your defined paths, like:
import { messages } from '#constants/responses'
import CandidatesService from '#modules/candidates/candidates.service'
import { IModule } from '#interfaces/module.interface'
etc...
The problem is the rule no-implicit-dependencies: true on the tslint.json. You can pass additional params to whitelist your custom paths:
"no-implicit-dependencies": [true, ["#custom-path", "#other-path"]],
for anyone who still struggles with this issue, but the below code at the top of the entry point file (main.ts).
don't forget to adjust the tsconfig.json file path if it is not in the default location
const tsConfig = require('../tsconfig.json');
const tsConfigPaths = require('tsconfig-paths');
tsConfigPaths.register({
baseUrl: __dirname,
paths: tsConfig.compilerOptions.paths,
});
I was able to do this with #zerollup/ts-transform-paths NPM package.
Install #zerollup/ts-transform-paths as dev dependency: yarn add -D #zerollup/ts-transform-paths
Setup following config of webpack + ts-loader.
const tsTransformPaths = require('#zerollup/ts-transform-paths');
module.exports = {
... // other config
module: {
rules: [
{
test: /\.(ts|tsx)$/,
loader: 'ts-loader',
options: {
getCustomTransformers: (program) => {
const transformer = tsTransformPaths(program);
return {
before: [transformer.before], // for updating paths in generated code
afterDeclarations: [transformer.afterDeclarations] // for updating paths in declaration files
};
}
}
}
]
}
};
See more in detail: https://github.com/zerkalica/zerollup/tree/5aee60287647350215c81d0b2da5a30717d9dccb/packages/ts-transform-paths

Resources