How to set path for dynamic import in webpack 4 - .net-core

I have a NET Core application with the following webpack config optimization and output sections located in ClientApp folder which is placed in the root of the project
optimization: {
splitChunks: {
cacheGroups: {
translations: {
test: /[\\/]node_modules[\\/]webapps-translations/,
name(module, chunks, cacheGroupKey) {
const moduleFileName = module.identifier()
.split('\\').pop().toLowerCase().replace('.json', '');
return `${moduleFileName}`;
}
}
}
}
},
output: {
path: path.resolve(path.join('..', 'wwwroot', 'js')),
publicPath: path.join('..', 'js'),
filename: `[name]${jsMin}.js`
}
I have the following dynamic import statement
import(
/* webpackMode: "lazy" */
/* webpackPrefetch: true */
/* webpackPreload: true */
`webapps-translations/assets/${lang}.json`).then(m => {
let translations = m.default;
// TODO: use translations
});
Webpack generates the files in the desire location but the dynamic import request path is wrong. My page URL is http://localhost:5001/api/mypage but the generated import path is http://localhost:5001/api/jsde.js. The generated webpack URL should be http://localhost:5001/js/de.js
How can I configure the right path for dynamic import?

Related

Could not resolve "~#blueprintjs/core/lib/css/blueprint.css" when using esbuild

I am unable to import blueprint.js css files using #import in a css file using esbuild - no webpack.
#import "~normalize.css";
#import "~#blueprintjs/core/lib/css/blueprint.css";
#import "~#blueprintjs/icons/lib/css/blueprint-icons.css";
I receieve the following errors.
Error: Build failed with 3 errors:
src/style.css:2:8: error: Could not resolve "~normalize.css" (mark it
as external to exclude it from the bundle)
src/style.css:3:8: error: Could not resolve
"~#blueprintjs/core/lib/css/blueprint.css" (mark it as external to
exclude it from the bundle)
src/style.css:4:8: error: Could not resolve
"~#blueprintjs/icons/lib/css/blueprint-icons.css" (mark it as external
to exclude it from the bundle)
My Builder.js File
const { start } = require('live-server')
const { watch } = require('chokidar')
const { build } = require('esbuild')
const fs = require('fs-extra')
const isDev = process.env.NODE_ENV !== 'production'
/**
* Live Server Params
* #link https://www.npmjs.com/package/live-server#usage-from-node
*/
const serverParams = {
port: 8000, // Set the server port. Defaults to 8080.
root: 'dist', // Set root directory that's being served. Defaults to cwd.
open: true // When false, it won't load your browser by default.
// host: "0.0.0.0", // Set the address to bind to. Defaults to 0.0.0.0 or process.env.IP.
// ignore: 'scss,my/templates', // comma-separated string for paths to ignore
// file: "index.html", // When set, serve this file (server root relative) for every 404 (useful for single-page applications)
// wait: 1000, // Waits for all changes, before reloading. Defaults to 0 sec.
// mount: [['/components', './node_modules']], // Mount a directory to a route.
// logLevel: 2, // 0 = errors only, 1 = some, 2 = lots
// middleware: [function(req, res, next) { next(); }] // Takes an array of Connect-compatible middleware that are injected into the server middleware stack
}
/**
* ESBuild Params
* #link https://esbuild.github.io/api/#build-api
*/
const buildParams = {
color: true,
entryPoints: ['src/index.jsx'],
loader: { '.js': 'jsx' },
outdir: 'dist',
minify: !isDev,
format: 'cjs',
bundle: true,
sourcemap: true,
logLevel: 'error',
incremental: true
}
;(async () => {
fs.removeSync('dist')
fs.copySync('public', 'dist')
const builder = await build(buildParams)
if (isDev) {
watch('src/**/*', { ignoreInitial: true }).on('all', () => {
builder.rebuild()
})
start(serverParams)
} else {
process.exit(0)
}
})()
Just remove the ~ prefix in path:
#import "normalize.css/normalize.css";
#import "#blueprintjs/core/lib/css/blueprint.css";
#import "#blueprintjs/icons/lib/css/blueprint-icons.css";
BTW, the path for normalize.css should be normalize.css/normalize.css

How to add path aliases to next.js?

Based on docs I know I can use a jsconfig.json file to manage paths.
But I have encountered two problems:
It's a JSON file and not a JS file. This means that I can't code in it. In Vite+React or CRACO we can write Node.js code to create path aliases.
It seems that the paths property does not work for jsconfig.json.
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"#": [
"components"
]
}
}
}
So, my first question is that how can I add path aliases to next.js via code?
And my second question is that why import Button from '#/Button' does not work while I have specified the # to point to compnents directory and the baseUrl to point to the root of the project?
Update
Let's say I have this structure:
- components
- Index
- Exports.js
- Hero.js
- Pricing.js
- Stats.js
- Testimonials.js
- Shared
- Button.js
- Exports.js
- Section.js
- Title.js
- pages
And inside each Exports.js I have exported all sibling modules:
import Hero from './Hero'
import Pricing from './Pricing'
import Stats from './Stats'
import Testimonials from './Testimonials'
export { Hero }
export { Pricing }
export { Stats }
export { Testimonials }
Then why this path alias does not work?
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"Index": [
"components/Index/Exports"
]
}
}
}
And inside index.js:
import { Hero, Pricing, Stats, Testimonials } from 'Index'

TypeError: Cannot read property 'forEach' of undefined after upgrade to Nextjs 11

Have upgraded my project to nextjs 11 and unfortunately some of my code is erroring out.
I have equally upgraded React from 16.0.0 version to 17.0.0 so I could then upgrade to next.js.
This is the code snippet that is erroring out and its located in my next.config.js file:
config.module.rules[1].oneOf.forEach((moduleLoader, i) => {
Array.isArray(moduleLoader.use) && moduleLoader.use.forEach((l) => {
if (l.loader.includes("css-loader") && l.options.modules && l.options.modules.exportLocalsConvention) {
l.options = {
...l.options,
modules: {
...l.options.modules,
exportLocalsConvention: "camelCase",
}
}
}
});
});
If I remove the code entirely a different error pops up related to svg config on the same file :
webpack: (config, { buildId, dev, isServer, defaultLoaders, webpack }) => {
// svg to react component loader
config.module.rules.push({
test: /\.svg$/,
use: [{
loader: '#svgr/webpack',
options: {
"svgoConfig": {
"plugins": [{ "cleanupIDs": false }]
}
}
}],
})
Any ideas on what is happening?
I know they have new related features but not entirely sure how to go about it and ensure my project runs similarly.
Thanks
Next.js 11 now uses webpack 5 under the hood so you need to update your webpack config accordingly.
There is a small migration guide here, but it does not cover all the changes obviously.
I think you can also opt-out of webpack 5 for now, if you want to update Next.js but don't want to mess with webpack config for now:
// add this key in your next.config
module.exports = {
webpack5: false,
}

Apply different css files between 2 sub roots

I have an angular app, which consists of a website and system.
so I have made 2 sub roots under app root, websiteMaster, and systemMaster.
CSS files of the website don't have to be loaded when I'm logged in.
CSS files of the systems don't have to be loaded when I'm logged out.
so I need to load CSS files in websiteMaster only for website sub root components and to load CSS files in systemMaster only for system sub root components.
Is there a way to apply that using Angular 8?
Thanks in advance
You've to manually load/unload css files in a main/root(whatever you want to call it) component in one of your subroot module.
Let suppose websiteMaster module has following structure
Routes:
// Wrapping all routes in a parent component
const routes: Routes = [
{ path: '', component: WebsiteMasterRootComponent, children: [
{ path: 'any-path', component: AnyComponent },
{ path: 'any-other-path', component: AnyOtherComponent },
]
}];
WebsiteMasterRootComponent: which will load and unload css files related to this module
export class WebsiteMasterRootComponent implements OnInit, OnDestroy {
// css files required for current module
private styles = [
{ id: 'css-file-1', path: 'assets/css/css-file-1.css' },
{ id: 'css-file-2', path: 'assets/css/css-file-2.css' },
{ id: 'css-file-3', path: 'assets/css/css-file-3.css' },
];
constructor() {}
ngOnInit() {
this.styles.forEach(style => this.loadCss(style));
}
ngOnDestroy() {
// remove css files from DOM when component is getting destroying
this.styles.forEach(style => {
let element = document.getElementById(style.id);
element.parentNode.removeChild(element);
});
}
// append css file to DOM dynamically when current module is loaded
private loadCss(style: any) {
let head = document.getElementsByTagName('head')[0];
let link = document.createElement('link');
link.id = style.id;
link.rel = 'stylesheet';
link.type = 'text/css';
link.href = style.path;
head.appendChild(link);
}}

CRA + Craco + multiple CSS themes

Folder structure:
src/index.tsx
src/themes/dark.scss
src/themes/light.scss
...
craco webpack modifications:
const path = require('path');
module.exports = {
webpack: {
configure: (webpackConfig, { env, paths }) => {
webpackConfig.entry.push(
path.join(process.cwd(), "src/themes/dark.scss"),
path.join(process.cwd(), "src/themes/light.scss")
);
webpackConfig.module.rules.splice(1, 0, {
test: /\.themes\/dark.scss$/,
use: [
{ loader: require.resolve('sass-loader') },
{ loader: require.resolve('css-loader') }
]
});
webpackConfig.module.rules[3].oneOf[5].exclude = /\.(module|themes)\.(scss|sass)$/;
webpackConfig.module.rules[3].oneOf[6].exclude = /\.themes\.(scss|sass)$/;
webpackConfig.module.rules[3].oneOf[7].exclude.push(/\.themes\.(scss|sass)$/);
return webpackConfig;
}
}
};
the intent is I am hoping obvious - we are trying to generate two theme css files from src/themes directory, which will be later changed manually with unloading / loading <link in DOM directly, I was inspired by Output 2 (or more) .css files with mini-css-extract-plugin in webpack and https://github.com/terence55/themes-switch/blob/master/src/index.js.
Now comes the troubles - after build process:
Creating an optimized production build...
Compiled successfully.
File sizes after gzip:
122.24 KB build/static/css/2.2e93dcba.chunk.css
762 B build/static/js/runtime~main.a8a9905a.js
191 B build/static/css/main.d0c4fa77.chunk.css
157 B build/static/js/main.2063d3e0.chunk.js
109 B build/static/js/2.9b95e8c0.chunk.js
(CSS files are OK, there are few generic CSS files and few of them are from libraries). But no theme files... I try to combine with file-loader, but it does not work either.
I would recommend configuring webpack to pack all assets related to a particular theme into a single chunk:
const themeFileRegex = /(\w+)\.theme\.(scss|sass)$/;
// recursively searches for a theme stylesheet in parent issuers
function getIssuerTheme(module) {
const matches = themeFileRegex.exec(module.resource);
if (matches) {
return matches[1];
} else {
return module.issuer && getIssuerTheme(module.issuer);
}
}
...
webpackConfig.optimization.splitChunks.cacheGroups = {
...webpackConfig.optimization.splitChunks.cacheGroups,
themes: {
test: getIssuerTheme,
name: m => {
const name = getIssuerTheme(m);
return `theme.${name}`;
},
reuseExistingChunk: false,
},
};
With that, you should get chunks named theme.light, theme.dark, etc.

Resources