Webpack 5 - Asset Modules - png|jpg - Webpack Error - reactjs

I am using the latest version of webpack for my react project.
I am attempting to load png or jpgs. I was trying with the old "loader"s however I was still getting the "unexpected token" when trying to load an imported image.
I found from googling that Webpack 5 now uses Asset Modules to load assets now.
I've used the recommend module rule below:
module: {
rules: [
{
test: /\.(?:ico|gif|png|jpg|jpeg)$/i,
type: 'asset/resource'
},
However when I attempt to build, I get this error:
Invalid configuration object. Webpack has been initialised using a configuration object that does not match the API schema.
- configuration.module.rules[0].type should be one of these:
"javascript/auto" | "javascript/dynamic" | "javascript/esm" | "json" | "webassembly/experimental"
-> Module type to use for the module
I have been on this for the last 7hr hours with no luck. Any assistance would be appreciated. :)

You can try this to match images of different types.
{
test: [/\.svg$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
loader: "file-loader",
options: {
name: "asset/resource/[name].[ext]"
}
}
make sure the path exists.

Tip: Double check whether both installed packages: webpack and webpack-cli are up-to-date.

Related

Less integration with a Nx React project

I'm trying to configure my first project with Nx.
My client explicitly request the use of React with Typescript, Nx and the Ant design UI Kit.
I've successfully created a new project with the required specification, at least using the CSS version of the Ant design kit.
Of course, I need to customize the UI kit with colors and other modification. According to the Ant documentation, I need to use the less styles in order to modify them.
I choose to enable the less style in Nx (for each react component I have a component-name.module.less file).
Now, if I try to import the antd less style, the build process fails with the following error:
> nx run react-ui-kit:build
Bundling react-ui-kit...
Error during bundle: SyntaxError: Inline JavaScript is not enabled. Is it set in your options? in /Users/luca/Jellyfish/Customers/client/libs/react-ui-kit/node_modules/antd/lib/style/color/bezierEasing.less on line 110, column 1:
109 // https://github.com/ant-design/ant-motion/issues/44
110 .bezierEasingMixin();
111
I understand that I should edit the less-build script in order to enable the javascript inlining, something like:
module: { rules: [{
test: /\.less$/,
use: [
{ loader: "style-loader" },
{ loader: "css-loader" },
{
loader: "less-loader",
options: {
lessOptions: {
javascriptEnabled: true,
}
}
}
]
}]}
Unfortunately, I can't understand where to put this configuration inside my nx project.
Did someone have a similar problem? Any suggestion?

Create-react-app + TypeScript + CSS Modules: Auto-generating type definitions without ejecting from CRA

Problem
create-react-app v2+ supports TypeScript and CSS Modules out of the box... separately. The problem arises when you try to use the two together. Facebook had an extensive discussion about this issue and ultimately closed it off on GitHub. So developers have to use hacks and other workarounds to get these two technologies to play nicely together alongside CRA.
Existing workaround:
You can manually create ComponentName.module.css.d.ts files with type definitions like this: export const identifierName: string. This allows you to take advantage of TypeScript's typing and VS Code's auto-complete when you go to import ComponentName.module.css. Unfortunately, this is extremely tedious.
Solution (?):
The folks over at Dropbox created typed-css-modules-webpack-plugin to address this issue; it auto-genertes those *.d.ts files for you. They show how to install it with yarn or npm and then give this minimal code example:
const path = require('path');
const {TypedCssModulesPlugin} = require('typed-css-modules-webpack-plugin');
module.exports = {
entry: './src/index.ts',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
},
module: {
rules: [
{
test: /\.tsx?$/,
loader: 'ts-loader',
},
{
test: /\.css$/,
use: [
'style-loader',
// Use CSS Modules
{
loader: 'css-loader',
options: {
modules: true,
},
},
],
},
],
},
// Generate typing declarations for all CSS files under `src/` directory.
plugins: [
new TypedCssModulesPlugin({
globPattern: 'src/**/*.css',
}),
],
};
Unfortunately, it's not immediately clear how I can use this with create-react-app. I'm not very knowledgeable when it comes to Webpack, and I'm using customize-cra to avoid ejecting out of create-react-app so I can customize the Webpack configs for some things I need. For example, Ant Design lets you import components on demand by using babel-plugin-import as detailed here:
https://ant.design/docs/react/use-in-typescript#Use-babel-plugin-import
Question: How can I convert the above Webpack configuration code to a customize-cra equivalent so that I don't have to eject out of CRA?
Okay, so I eventually did figure this out, and I wrote a blog post on the subject for anyone who runs into a similar issue:
https://aleksandrhovhannisyan.github.io/blog/dev/how-to-set-up-react-typescript-ant-design-less-css-modules-and-eslint/#3-create-react-app-css-modules-and-typescript-
The solution uses the typescript-plugin-css-modules plugin. Here are the relevant bits from my blog post:
yarn add -D typescript-plugin-css-modules
After it’s installed, add the plugin to your tsconfig.json:
{
"compilerOptions": {
"plugins": [{ "name": "typescript-plugin-css-modules" }]
}
}
Next, create a file named global.d.ts under your src directory. You don’t have to name it global, by the way; you can name the file whatever you want, as long as it has the .d.ts extension. Enter these contents:
declare module '*.module.less' {
const classes: { [key: string]: string };
export default classes;
}
If you want to also use SASS or CSS, simply add more module declarations and change the .less extension.
We’re almost done! Per the plugin’s usage instructions, if you want intellisense to work in VS Code, you’ll need to force VS Code to use your workspace version of TypeScript instead of the globally installed version. Remember when we installed TypeScript via CRA at the very beginning? That’s our workspace version of TypeScript.
Here’s how to use the workspace version of TypeScript in VS Code:
Open any TypeScript file.
Click the version number on the blue status bar at the bottom of VS Code.
Select Use Workspace Version (3.7.3 as of this writing).
Here’s a screenshot to make that clearer:
Once you do that, VS Code will create a .vscode directory in your project for workspace settings.
At this point, you're all set to use CSS Modules with TypeScript.
UPDATE 2022
Note: If you're using react-scripts#2.1.x or higher you don't need to use custom definitions like
declare module '*.module.less' {
const classes: { [key: string]: string };
export default classes;
}
Custom definitions
Note: Create React App users can skip this section if you're using react-scripts#2.1.x or higher.
Also you can add this VS code setting to you local JSON settings file:
{
"typescript.tsdk": "node_modules/typescript/lib",
"typescript.enablePromptUseWorkspaceTsdk": true
}
This will ensure that VS Code will use the project’s version of Typescript instead of the VS Code version and will prompt you to do so if you aren’t already.
Well, everything is correct as said AlexH.
1 in tsconfig.ts.
{
"compilerOptions": {
"plugins": [{ "name": "typescript-plugin-css-modules" }]
}
}
2 in global.d.ts
declare module '*.module.less' {
const classes: { [key: string]: string };
export default classes;
}
But Also in tsconfig you should write
"include": [
"global.d.ts",
...
]

How to configure the webpack configurations in create-react-app

I have a question or problem.
I'm using React v.16 so when I create a project I did with create-react-app that webpack is already preconfigured. And I want work with ol-cesium, and in npmjs I see that I have to:
create an alias to the goog directory. With webpack:
resolve: {
alias: {
'goog': path_to_goog,
}
}
If I dont create a webpack file show me this error:
./node_modules/olcs/AbstractSynchronizer.js
107:22-35 "export 'getUid' (imported as 'olBase') was not found in 'ol/index.js'
How can solve it??? And what is path_to_goog???
EDIT
Thanks to Shishir Anshuman for your help.
Now I add alias on webpack.config.dev.js and webpack.config.prod.js but some me a lot errors.
resolve: {
// This allows you to set a fallback for where Webpack should look for modules.
// We placed these paths second because we want `node_modules` to "win"
// if there are any conflicts. This matches Node resolution mechanism.
// https://github.com/facebookincubator/create-react-app/issues/253
modules: ['node_modules', paths.appNodeModules].concat(
// It is guaranteed to exist because we tweak it in `env.js`
process.env.NODE_PATH.split(path.delimiter).filter(Boolean)
),
// These are the reasonable defaults supported by the Node ecosystem.
// We also include JSX as a common component filename extension to support
// some tools, although we do not recommend using it, see:
// https://github.com/facebookincubator/create-react-app/issues/290
// `web` extension prefixes have been added for better support
// for React Native Web.
extensions: ['.web.js', '.mjs', '.js', '.json', '.web.jsx', '.jsx'],
alias: {
// Support React Native Web
// https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/
'react-native': 'react-native-web',
// Ol-Cesium
'goog': '../node_modules/olcs/goog',
},
plugins: [
// Prevents users from importing files from outside of src/ (or node_modules/).
// This often causes confusion because we only process files within src/ with babel.
// To fix this, we prevent you from importing files out of src/ -- if you'd like to,
// please link the files into your node_modules/ and let module-resolution kick in.
// Make sure your source files are compiled, as they will not be processed in any way.
new ModuleScopePlugin(paths.appSrc, [paths.appPackageJson]),
],
},
In console show me this error:
./node_modules/olcs/AbstractSynchronizer.js
107:22-35 "export 'getUid' (imported as 'olBase') was not found in 'ol/index.js'
__stack_frame_overlay_proxy_console__ # index.js:2178
handleErrors # webpackHotDevClient.js:178
./node_modules/react-dev-utils/webpackHotDevClient.js.connection.onmessage # webpackHotDevClient.js:211
./node_modules/sockjs-client/lib/event/eventtarget.js.EventTarget.dispatchEvent # eventtarget.js:51
(anonymous) # main.js:274
./node_modules/sockjs-client/lib/main.js.SockJS._transportMessage # main.js:272
./node_modules/sockjs-client/lib/event/emitter.js.EventEmitter.emit # emitter.js:50
WebSocketTransport.ws.onmessage
In the Codesandbox provided by you, I was unable to find the root cause, but I noticed the following:
I noticed that you have used the ES6 import statement:import OLCesium from "olcs/OLCesium";.
But as per this issue, the module is not yet ported to ES6.
I have never used this library before, So it's hard to figure out what exactly is going on.
Did you try installing https://www.npmjs.com/package/geom ? Since the error says 4.6.4/geom/Point.js is missing.

Webpack 1 + sass (in react) - leave my images alone

I have a project in React.js with SASS and using Webpack 1.
I have images folders with all the images and other assets' folders.
I do not want webpack to do anything with images, I want them to be loaded at the runtime by url.
I solved it in JSX by using image urls inline in the jsx code (rather then importing them) and it's working great.
But when I'm trying to do the same in SASS, it's different:
I used to refer to them in absolute pass /images/abc.png and it worked.
I didn't even had a webpack loader for them, it just worked.
But I had to change it to the relative path ../../www/images/abc.png and it's all broke down:
It refuses to work without webpack loader - just gives errors for each image.
I've tried using file-loader, but it copies all sass's used images into build folder.
I've tried using url-loader, but it just included the images into resulting css file making it enormously bloated.
So, what could I use to ignore the images from sass and just address them by url in the runtime?
Thanks
One possibility is to set the url option of the css-loader to false, so webpack won't touch the urls. Your rule for .scss could look something likes this (assuming you use extract-text-webpack-plugin):
Webpack 1:
{
test: /\.scss$/,
loader: ExtractTextPlugin.extract('style-loader', 'css-loader?url=false!sass-loader')
},
Webpack 2:
{
test: /\.scss$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: [
{ loader: 'css-loader', options: { url: false } },
{ loader: 'sass-loader' }
]
})
}
But that ignores all urls not just your images. If that is a problem you could use file-loader with the option emitFile: false so it won't copy your files. But you'll need some workaround to get the correct path. When using [path] in the name it will use the relative path from the context. Because you're building it to a directory (e.g. build/) you'll need to go up one directory (../) by setting the publicPath option. Which would give you the following rule:
Webpack 1:
{
test: /\.png/,
loader: 'file-loader?emitFile=false&name=[path][name].[ext]&publicPath=../'
},
Webpack 2:
{
test: /\.png/,
loader: 'file-loader',
options: {
emitFile: false,
name: '[path][name].[ext]',
publicPath: '../'
}
}
If you've set context in your webpack config or your output CSS file is more than one level deep in the build directory, you'll need to tweak the publicPath option.

How to solve webpack2 error: You may need an appropriate loader to handle this file type?

I am trying to convert my reactjs/webpack/gulp app to webpack2. I am using the webpackconfig+.babelrc file and package.json from this project as a starting point:
https://github.com/ModusCreateOrg/budgeting-sample-app-webpack2
This is the gulpcode:
var gulp = require('gulp');
var webpackStream = require('webpack-stream');
var webpack2 = require('webpack');
gulp.task('default', function() {
return gulp.src('app/app.js')
.pipe(webpackStream({/* options */}, webpack2))
.pipe(gulp.dest('dist/'));
});
When I run 'gulp' I get this error:
stream.js:74
throw er; // Unhandled stream error in pipe.
^
Error: ./app/app.js
Module parse failed: C:\myapp\app\app.js Unexpected token (11:4)
You may need an appropriate loader to handle this file type.
|
| ReactDOM.render(
| <Provider>
| <App />
| </Provider>,
Which loader do I need and where do I configure this?
You're not actually using webpack.config.js so presumably you're configuring the options in the Gulpfile. But you commented the options as /* options */ which is the important bit, where you actually configure webpack.
You configure the loaders in these options under module.rules (see also Concepts - Loaders). In your case you need the babel-loader with babel-preset-react to be able to transpile JSX syntax, the preset should already be in the .babelrc config you're using. You just need to add the loader to your options in the Gulpfile so that your .js and .jsx files are passed through that loader (using the same rule as in the project you linked):
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: [
'babel-loader'
],
}
]
}
Instead of defining the options in your Gulpfile you can define a webpack.config.js and then just require it and pass it to webpackStream. This file is automatically used when you use webpack directly (without Gulp), so it's very convenient to have that config if you ever want to run it outside of Gulp. It's good idea to get familiar with webpack. A good starting point is the Core Concepts of the official docs.
Usually an object is exported, which you can use directly in webpackStream, but in the project you linked, it exports a function which returns the configuration object based on the environment used. To use it directly in your Gulpfile you would do the following:
var gulp = require('gulp');
var webpackStream = require('webpack-stream');
var config = require('./webpack.config');
gulp.task('default', function() {
return gulp.src('app/app.js')
.pipe(webpackStream(config()))
.pipe(gulp.dest('dist/'));
});
config() returns the development options and to get the production config you'd need to call config({ prod: true }). You probably don't want to use exactly that config but use your own which you can just export as a plain object, so you don't need to call a function.

Resources