Next.js Unable to serve dynamic images on the runtine - reactjs

So I am using Next.js API for the backend of my project and Mongodb for the database.
I have to serve images which have been uploaded by users on the runtine. As these files weren't available yet during the build time, they are not recognized as static files which can be stored in public directory.
I have tried next-images, added some configurations in the next.config.js and in my code: <img src={require(../../../images/${picture.src})} alt={picture.legend} />.
But still I have this error:.
I also tried with file-loader but still got no luck.
What did I miss?
Thanks for any reply!

This configuration has worked for me in the past when running into these issues with loading images and/or fonts:
npm install url-loader --save-dev
next.config.js
module.exports = {
webpack: function (config) {
config.module.rules.push({
test: /\.(eot|woff|woff2|ttf|svg|png|jpg|gif)$/,
use: {
loader: 'url-loader',
options: {
limit: 100000,
name: '[name].[ext]',
},
},
});
return config;
},
}

Related

Importing a react component into an existing react project from npm package

I have created an npm package with the scoped name '#bpmg/mycomponent' with a single react component. I have published this to a local npm registry (verdaccio).
I have created a new react project to test this package, using create-react-app.
I have installed my npm package successfully and can import the component into my project.
However, webpack (from create-react-app scripts) complains about my imported file.
support for the experimental syntax 'jsx' isn't currently enabled
So I install react-app-rewired and try to override the webpack config to "include" this one node_module in the webpack bundler.
Here is what I have
/* config-overrides.js */
const path = require('path');
module.exports = {
webpack: function (config, env) {
config.module.rules= [
{
test: /\.(js|jsx)$/,
exclude: /node_modules\/(?!(#bpmg)\/).*/,
include: [
path.join(__dirname, 'src')
],
loader: 'babel-loader',
options: { presets: ['#babel/env', '#babel/preset-react'] },
}
];
return config;
}
}
This fails to run
ERROR in ./node_modules/#bpmg/myComponent/src/myComponentMainFile.js
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
Where it chokes on the first bit of jsx syntax it encounters.
Where am I going wrong here?

sharing react between microfrontend bundles without CDN

I am building an app using a microfrontends architecture with the Single-Spa framework.
I have:
A root config web app: Defines the layout of the apps and includes each microfrontend as an NPM dependency
N Microfrontends: React apps which are loaded into the root config app.
Because each microfrontend is using React, I don't want to bundle it everytime. Instead I want to have the root config app specify React as a dependency and then it can be loaded by each microfrontend.
I have declared react and react-dom as webpack externals so they are not bundled but I think this will only work if I include React from CDN in my index.html of the root config app. Is there a way to configure webpack so that it will include React in the root config and make it available to every microfrontend? I can't use public CDNs in my firm.
Thanks!
In the "Getting Started: Quick start" guide, we cover how to add shared dependencies, and the example specifically shows adding React and ReactDOM to the import map.
You should not try to bundle React into the root-config, since modules bundled into an application by Webpack are namespaced and not shared globally. Instead, per your requirement, you can host those React files in your own CDN or even serve them locally though the root-config because ultimately there are static files. The location of where those files are loaded from is not relevant to SystemJS as long as it can load them. This means you can go as simple as copying those files locally and serving them from the root-config server, to as complicated as setting up your own unpkg server.
Yes, we can do that not just for the React Package but with all the dependencies and share them between all the micro-frontend apps.
Webpack 5, provides the support of ModuleFederationPlugin in which you can define the list of packages. Example:-
Import Package.json in the Webpack configuration and add following plugin
const packageJson = require('../package.json');
{
plugins: [
new ModuleFederationPlugin({
name: <AppName>,
filename: 'remoteEntry.js',
exposes: {
'./App': <PathToFile>,
},
shared: {
...packageJson.dependencies,
}
}),
],
}
You can explicitly define only the packages name which you want to share.
Check out more about ModuleFederationPlugin
If you want to have flexibility in micro frontend, that is, if you want each micro frontend to be deployed independently of each other, you can use client-side intgration.
React
You can use a CDN for static files. (image, fonts, pdf, doc) Webpack module federation can be used for client-side integration.
Configuring an example webpack and module federation.
We divide the webpack config files into 3 parts. for common, development, production
webpack.common.js
module.exports = {
module: {
rules: [
{
test: /\.m?js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['#babel/preset-react', '#babel/preset-env'],
plugins: ['#babel/plugin-transform-runtime'],
},
},
},
],
},
};
webpack.dev.js
const { merge } = require('webpack-merge');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');
const commonConfig = require('./webpack.common');
const packageJson = require('../package.json');
const devConfig = {
mode: 'development',
output: {
publicPath: 'http://localhost:8082/',
},
devServer: {
port: 8082,
historyApiFallback: {
index: 'index.html',
},
},
plugins: [
new ModuleFederationPlugin({
name: 'auth',
filename: 'remoteEntry.js',
exposes: {
'./AuthApp': './src/bootstrap',
},
shared: packageJson.dependencies,
}),
new HtmlWebpackPlugin({
template: './public/index.html',
}),
],
};
module.exports = merge(commonConfig, devConfig);

Webpack+SemanticUI+React: process is not defined

I have found numerous posts about the Webpack error:
Uncaught ReferenceError: process is not defined
most of which suggest adding a plugin to the webpack.config.js:
plugins: [
// ...
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify(process.env.NODE_ENV || 'development')
}
}),
// ...
]
however this does not seem to do the trick in my case.
To make things easy, I have created a repo with the bare minimum to setup SemanticUI-React with Webpack, which should be straightforward to navigate. My config in webpack.config.js is heavily inspired from this recent tutorial which seems to have a lot of positive comments.
To reproduce the error, just clone the repo on your machine (I use yarn, but this should work with npm too):
git clone https://github.com/sheljohn/minimal-semantic-react
cd minimal-semantic-react/
yarn install
yarn run serve
which opens at localhost:3000, and the error can be seen in the developer console.
As far as I understand, it seems that when React loads, it is looking to determine whether production or development mode is set, using the variable process.env.NODE_ENV, which is undefined in the browser.
This might be related to the target field in the Webpack config (set to web by default); but since React is loaded from CDN, prior to the bundle, I guess it doesn't know about what WebPack is doing, which makes me perplex as to why adding a plugin in the config would change anything...
Hence my question: is it possible to use semantic-ui-react by declaring the big libs (React, ReactDOM, semantic) as externals? Everything works fine if I bundle them, but the bundle ends up around 4MB, which is quite big.
Additional Details
Error as seen in Chrome (OSX High Sierra, v66.0.3359.181, dev console):
react.development.js:14 Uncaught ReferenceError: process is not defined
at react.development.js:14
(anonymous) # react.development.js:14
and code excerpt at line 14:
if (process.env.NODE_ENV !== "production") {
File webpack.config.js
const path = require("path");
const webpack = require("webpack");
const publicFolder = path.resolve(__dirname, "public");
module.exports = {
entry: "./src/index.jsx",
target: "web",
output: {
path: publicFolder,
filename: "bundle.js"
},
devServer: {
contentBase: publicFolder,
port: 3000
},
externals: {
'jquery': 'jQuery',
'lodash': '_',
'react': 'React',
'react-dom': 'ReactDOM',
'semantic-ui-react': 'semantic-ui-react'
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader'
}
}
]
},
plugins: [
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify(process.env.NODE_ENV || 'development')
}
}),
new webpack.HotModuleReplacementPlugin()
]
};
File .babelrc
{
"presets": ["env", "react"]
}
I think I finally solved this:
Mistake #1: I was using cjs versions of the React libs from cdnjs, when I should have been using umd instead. Although UMD style is ugly, it seems to work fine within browsers, whereas CommonJS uses require for example. See this post for a comparison of AMD / CommonJS / UMD.
Mistake #2: in webpack.config.js, the "name" for the external semantic-ui-react should be semanticUIReact (case sensitive). This is what is defined in the window global when the script is loaded from the CDN (e.g. like jQuery or React).
I updated the repository with these fixes, and you should be able to reproduce that working example on your machine. This repository contains the bare minimum needed to get SemanticUI, React and Webpack working together. This would have saved me a lot of time, so hopefully other people get to benefit from that!
Everything works fine if I bundle them, but the bundle ends up around 4MB, which is quite big.
It's because you bundle them in "development" mode. Try using "production" in your script instead, it will be much smaller.
"build": "webpack --mode production"
If you bundle everything in production, without specifying external, it will be better for a standalone app.

Serve apple-app-site-association with webpack

I'm new to webpack and I can't seem to find a way to serve the Apple Universal Links file under / using webpack.
Could you please advise how to get /apple-app-site-association working?
if you want to serve apple-app-site-association through webpack you could add loader
and add import for this file in main.js for example
{
test: /apple-app-site-association/,
exclude: /node_modules/,
loader: [
{
loader:'file-loader',
options: {
name: '/[name]',
}
}]
}

external url in webpack alias

My team moved all the images of company website into a CDN. (https://cdn.irobo.co.kr/images)
However, I'd like to use those images without changing current code base, which has a lot of: (reactjs code)
<image src={require('img/common/logo.jpg')} />
here's the webpack config for the website:
{
module: {
loaders:[{
test: /\.(png|jpg)$/,
loader: 'file-loader?name=[name].[ext]',
}],
}
...
resolve: {
alias: {
img: path.join(srcPath, 'app/img'),
}
}
}
Here's what I tried:
...
resolve: {
alias: {
img: 'https://cdn.irobo.co.kr/images',
}
}
}
Bundling assets from external urls with Webpack
The url-loader plugin for webpack gives you the ability to take use assets from external url by encoding them in base64.
The url loader works like the file loader, but can return a Data Url
if the file is smaller than a byte limit.
The limit can be specified with a query parameter. (Defaults to no
limit)
Remember to install the url-loader plugin as a project dependency.
npm install --save-dev url-loader
Configure the url-loader plugin
Here is a sample webpack config to set up the url-loader plugin.
webpack.config.js
module.exports = {
entry: './main.js',
output: {
path: './build', // This is where the images and js will go
publicPath: 'http://mycdn.com/', // used to generate URLs to e.g. images
filename: 'bundle.js'
},
module: {
loaders: [
// use ! to chain loaders
{ test: /\.less$/, loader: 'style-loader!css-loader!less-loader' },
{ test: /\.css$/, loader: 'style-loader!css-loader' },
// inline base64 URLs for <=8k images, direct URLs for the rest
{ test: /\.(png|jpg)$/, loader: 'url-loader?limit=8192' }
]
}
};
Import the assets in your app
app.jsx
import image from '../build/image.jpg';
<img src={image} />

Resources