Load images using React/Webpack - reactjs

I set up the rule in webpack to load png images:
{
test: /\.(jpe?g|png|gif|svg)$/i,
loaders: [
'file?hash=sha512&digest=hex&name=[hash].[ext]',
'image-webpack?bypassOnDebug&optimizationLevel=7&interlaced=false'
]
}
That I found here: cannot load png files with webpack, unexpected character
Webpack seems to be working fine, giving no errors. So, I tried loading the png images paths that are located at app_folder/public/images/pca inside the render method:
importAll = (r) => {
return r.keys().map(r);
}
render() {
const pca_images = this.importAll(require.context('../public/images/pca',
false, /\.(png|jpe?g|svg)$/));
console.log('pca_images')
console.log(pca_images)
...
}
When I launch the app I do not see any errors but the pca_images is an empty array. The component itself is located at app_folder/views/. I tried loading the images also directly like that:
<img src={ require('../public/images/image1.png') } />
But whatever path I specify, it is just not working giving an error. I need to load all images from the folder app_folder/public/images/pca though, not just statically since I do not know the names of the images beforehand. Any suggestions would be greatly appreciated.

The solution that worked for me was to add the rule to the webpack.config.js:
{
test: /\.(jpe?g|gif|png|svg)$/i,
use: [
{
loader: 'url-loader',
options: {
limit: 10000
}
}
]
}
This rule I found here: ReactJS and images in public folder
Then I needed to run two commands in terminal:
npm install url-loader --save-dev
npm install file-loader --save-dev
And finally loading from the folder (see the question, render method) started working.

Related

How can I fix the "Failed to parse source map from ..." errors in my ReactJS/TS project

I have a ReactJS project where I wanted to use a Barcode-Scanner npm module with the name html5-qrcode, but I always get this error:
Failed to parse source map from 'C:\...\node_modules\html5-qrcode\third_party\index.js.map' file: Error: ENOENT: no such file or directory, open 'C:\...\node_modules\html5-qrcode\third_party\index.js.map'
And then there are errors like: (seperated for readability)
WARNING in ./node_modules/html5-qrcode/esm/camera/core-impl.js Module Warning (from ./node_modules/source-map-loader/dist/cjs.js):
Failed to parse source map from 'C:\...\node_modules\src\camera\core-impl.ts' file: Error: ENOENT: no such file or directory, open 'C:\...\node_modules\src\camera\core-impl.ts'
I thought it might be an TS error, because every file of the second error part has a .ts ending.
So I made a new ReactTS project with all components and co in it, but I still get the same error.
I thought it might be an TS error, because every file of the second error part has a .ts ending. So I made a new ReactTS project with all components and co in it, but I still get the same error.
It seems like the npm package has issues with its source maps and webpacks's source-map-loader module is not able to process them. This doesn't really affect the application itself but having all those warnings is annoying.
I came across two solutions: either force the source-map-loader to skip the culprit package or ignore source-map warnings all together.
To achieve either solution, you'll need to be able to override the webpack.config.js. How to override it really depends on the framework you use to run your React apps (I have mine setup using NX)
Solution 1: Ignore source-mapping warnings (Easiest)
Add ignoreWarnings: [/Failed to parse source map/] to your webpack configuration.
E.g.
const { merge } = require('webpack-merge');
module.exports = (config) => {
return merge(config, {
ignoreWarnings: [/Failed to parse source map/]
});
};
Your webpack.config.js will look a lot different than this.
The idea is to add (or override) ignoreWarnings with the pattern of the message it should ignore.
Solution 2: Skip source-map-loading for culprit package (Cleanest?)
const { merge } = require('webpack-merge');
module.exports = (config, context) => {
return merge(config, {
module: {
rules: [
{
enforce: 'pre',
test: /\.js$/,
use: [
{
loader: 'source-map-loader',
options: {
filterSourceMappingUrl: (url, resourcePath) => {
// #zxing has issues with its source maps
if (/#zxing/i.test(resourcePath)) {
return false;
}
return true;
}
}
}
]
}
]
}
});
};
The idea here is to override the source-map-loader rules and skip its execution if the current resource matches the regex. In my case, I want to skip any resource that contains #zxing.
I tried using hte exclude option but I had no luck with that and opted to use the filterSourceMappingUrl instead. Maybe it works for you though. Remember, the pathing has to be absolute so you might need to adapt the excluded pathings.
More details here
const { merge } = require('webpack-merge');
module.exports = (config, context) => {
return merge(config, {
module: {
rules: [
{
enforce: 'pre',
test: /\.js$/,
use: ['source-map-loader'],
exclude: ['/node_modules/#zxing']
}
]
}
});
};
Hope this helps.
Cheers.
add react-app-rewired to your project:
yarn add --dev react-app-rewired
or
npm install react-app-rewired --save-dev
modify your package.json with those lines:
"start": "react-app-rewired start",
"build": "react-app-rewired build",
"test": "react-app-rewired test",
create a file called config-overrides.js in project root (same folder as package.json) with this content:
module.exports = function override(config) {
return {
...config,
ignoreWarnings: [
{
module: /node_modules\/stylis-plugin-rtl/,
},
],
}
}
change "stylis-plugin-rtl" in config-overrides.js above to whichever name of library that has an invalid build and throwing errors.
source maps errors should no longer appear.

Storybook - no stories showing up in typescript project with custom webpack / babel

I am trying to set up Storybook in a project. My project is runing on react#^16, and I'm using typescript, with a custom babel and webpack setup for development and build. To set up storybook, I did
npx sb init
This installs everything needed. It puts a .storybook folder in the root folder, and a stories folder in my src folder with some prefab components and stories in tsx format (which is what I want):
The .storybook/main.js file seems fine:
module.exports = {
"stories": [
"../src/**/*.stories.mdx",
"../src/**/*.stories.#(js|jsx|ts|tsx)"
],
"addons": [
"#storybook/addon-links",
"#storybook/addon-essentials"
]
}
And the average .stories.js file automatically installed by npx sb init also seems fine:
import React from 'react';
// also exported from '#storybook/react' if you can deal with breaking changes in 6.1
import { Story, Meta } from '#storybook/react/types-6-0';
import { Header, HeaderProps } from './Header';
export default {
title: 'Example/Header',
component: Header,
} as Meta;
const Template: Story<HeaderProps> = (args) => <Header {...args} />;
export const LoggedIn = Template.bind({});
LoggedIn.args = {
user: {},
};
export const LoggedOut = Template.bind({});
LoggedOut.args = {};
But when I run npm run storybook, the storybook landing page has no stories. Even though it had installed some default stories to start playing with. It says:
Oh no! Your Storybook is empty. Possible reasons why:
The glob specified in main.js isn't correct.
No stories are defined in your story files.
As requested, here is a link to the repo so you can dig a bit deeper into the structure, weback config, etc. Note I have not committed the npx sb init changes yet, so you won't see the files there, only my starting point just before running the sb init.
I haven't had any issues getting npx sb init to work with a standard create-react-app, but with my custom webpack build and typescript, its just empty. What's going wrong?
Edit: Additional detail
I realize that just running npx sb init, then npm run storybook throws this error:
ERROR in ./.storybook/preview.js-generated-config-entry.js
Module not found: Error: Can't resolve 'core-js/modules/es.array.filter'
Based on this thread, installing core-js#3 solves the problem and storybook runs, though with no stories.
It seems like the babel plugin transform-es2015-modules-amd doesn't fit right with storybook since sb still uses your babel configuration.
You might need to remove it then it would work:
{
"plugins": [
// "transform-es2015-modules-amd", // Remove this plugin
]
}
If you want to have a special babel configuration for storybook, place it .storybook/.babelrc so the configuration would be simple like this:
.storybook/.babelrc:
{
"presets": ["#babel/preset-env", "#babel/preset-react", "#babel/preset-typescript"]
}
NOTE: You might miss to forget install #babel/preset-typescript to help you transform your typescript code.
Maybe you have problems with the stories path, try to save only "../src/**/*.stories.js" in your config to see if its the reason
"stories": [
"../src/**/*.stories.mdx",
"../src/**/*.stories.#(js|jsx|ts|tsx)"
]
In case of dealing with arcgis-js-api in sb, you have to declare #arcgis/webpack-plugin in storybook's webpack configuration by adding to its config.
Here are a few steps you have to do:
Add webpackFinal property in .storybook/main.js with following content:
const ArcGISPlugin = require('#arcgis/webpack-plugin');
module.exports = {
// ...
webpackFinal: (config) => {
// Add your plugin
config.plugins.push(
new ArcGISPlugin(),
);
// Since this package has used some node's API so you might have to stop using it as client side
config.node = {
...config.node,
process: false,
fs: "empty"
};
return config;
}
};
One more thing to be aware of, some components are importing scss files, so you might need to support it by adding a scss addon '#storybook/preset-scss'
// Install
npm i -D #storybook/preset-scss css-loader sass-loader style-loader
// Add to your current addons
{
addons: ['#storybook/addon-links', '#storybook/addon-essentials', '#storybook/preset-scss'],
}
Like a tmhao2005 say. Storybook still uses your babel configuration. And this is the intended behavior. This thread at github also describes how the fix similar issue.
Updated your config .storybook/main.js.
If you use .babelrc:
babel: async options => ({ ...options, babelrc: false })
Or .babel.config.js:
babel: async options => ({ ...options, configFile: false })

Webpack pdf file loader

This is the error:
"Build failed!
× ERROR ./media/fonts/handFont3.otf 1:4.
Module parse failed: Unexpected token (1:0)
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
(Source code omitted for this binary file)
# ./index.js 3:0-37
# ../node_modules/preact-cli/lib/lib/entry.js
# multi ../node_modules/preact-cli/lib/lib/entry webpack-dev-server/client webpack/hot/dev-server"
I'm trying to import pdf into preact component to make it build so I can get the link to the page with pdf file. Here is how:
import pdfFile from '../../media/images/pdfFile.pdf'
<a href={pdfFile} target="_blank"...
It didn't work, so I Googled this two solutions to add in wepback.config.js:
module.exports = {
module: {
rules: [
{
test: /\.(png|svg|jpg|gif|pdf)$/,
use: ['file-loader']
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/,
use: ['file-loader']
},
]
},
};
and
{
test: /\.(pdf)$/,
use: ['url-loader']
},
I do manually make webpack.config work by this string:
--config webpack.config.js
And file is working, but result is the same. I'm still getting the error. And the same with otf fonts.
Thank you.
I figured out the solution. You can't use webpack config with preact config together.
So I removed webpack config and changed preact one to this:
export default (config, env, helpers, options) => {
const rule = {
test: /\.(otf|pdf)$/,
loader: 'file-loader'
}
config.module.rules.push(rule);
}

gatsby-remark-vscode not displaying correct color theme

I'm trying to format code blocks in markdown files for posts to a website with Gatsby.
I would like the code blocks to be displayed in one of VSCode's color themes (Dark +, for instance). I have npm installed gatsby-remark-vscode, and put the plugin in my gatsby-config.js file:
plugins: [
{
resolve: 'gatsby-transformer-remark',
options: {
plugins: [{
resolve: 'gatsby-remark-vscode',
options: {
colorTheme: 'Dark+ (default dark)',
injectStyles: true,
extensions: [{
identifier: 'sdras.night-owl',
version: '1.1.3'
}],
extensionDataDirectory:
path.resolve('extensions'),
logLevel: 'error'
}
}]
}
},
]
I have required 'path' at the top of my gatsby-config.js file:
const path = require('path');
I have imported the stylesheet in my gatsby-browser.js file:
import 'gatsby-remark-vscode/styles.css';
I have used back-ticks to format in my markdown file (the file that contains the blog post) like this:
```js
(CODE EXAMPLE)
```
When I npm run develop, I do not see the correct VSCode formatting for the code block, just a code block similar to what we see on StackOverflow code blocks. I would greatly appreciate any advice on how to render the correct theme in my code blocks.
Oops - looks like I was using a previous version of gatsby-remark-vscode. Updating the version and following the config instructions in the README solved this.

How to use ng-annotate with hybrid app based on angular-cli

I'm working on an Angular.js project written with TypeScript. We're trying to evaluate whether to upgrade to Angular 8 and we're stuck with how to use ng-annotate with angular-cli's webpack configuration.
I believe that this can be achieved either by using the #angular-builders/custom-webpack tool or by using ngx-build-plus tool but I had not succeeded with neither of them.
My current attempt includes a partial webpack file for ngx-build-plus with the following configuration :
module: {
rules: [
{
test: /\.ts$/,
loaders: ['ng-annotate-loader?ngAnnotate=ng-annotate-patched'],
},
{
test: /\.tpl\.html$/,
loader: 'ng-cache-loader?-url&module=templates&prefix=src:./**/'
}
]
},
};
Having this, when I run ng serve --extra-webpack-config webpack.partial.js -o I get the following error : NonErrorEmittedError: (Emitted value instead of an instance of Error) error: couldn't process source due to parse error,Unexpected token
The token to which it refers, is simply the type declaration for a method parameter. So I'm guessing that there is some conflict with the loader that angular-cli already uses for TypeScript files but I don't know how to resolve this.
Is there any input on how to solve this either using one of the two tools or something else?
So, the way to do this is by using webpack-merge and custom-webpack.
This is the configuration to run ng-annotate with Typescript files :
module.exports = (config, options) => {
const customConfig = {
module: {
rules: [
{
test: /\.ts$/,
loaders: ['ng-annotate-loader?ngAnnotate=ng-annotate-patched'],
},
{
test: /\.tpl\.html$/,
loader: 'ng-cache-loader?-url&module=templates&prefix=src:./**/'
}
]
}
};
return merge.strategy({
'module.rules': 'prepend'
})(config, customConfig)
};
The key part is the merge.strategy call which will make sure that the loaders of the custom configuration will be prepended to the ones that angular-cli already sets up.
After several hours of looking at alternatives, the solution that worked the best for me was using babel-plugin-angularjs-annotate by:
Creating a new project
Installing babel and babel-plugin-angularjs-annotate
Executing babel, which takes the files from src, adds the annotations, and puts the result in the folder output.
For others needing the complete solution, this is what I executed:
mkdir babel-project && cd babel-project
npm init -y
npm install -D babel-cli babel-plugin-angularjs-annotate
Create .babelrc and add this:
{
"presets": [],
"plugins": [ "angularjs-annotate" ]
}
Finally execute babel:
npx babel src -d build --extensions .ts
This takes files like:
import * as _ from "underscore";
import "#app2/hello/chao"
const greeting = () => "Hello World"
angular.module("MyMod")
.controller("MyCtrl", ($scope, HelloClient) => {
HelloClient.add($scope, greeting);
});
And turns them into:
import * as _ from "underscore";
import "#app2/hello/chao";
const greeting = () => "Hello World";
angular.module("MyMod").controller("MyCtrl", ["$scope", "HelloClient", ($scope, HelloClient) => {
HelloClient.add($scope, greeting);
}]);
Update
Using babel-plugin-angularjs-annotate messed a lot with my formatting, so I ended up copying&pasting just the relevant parts of the Babel output, which took some hours.

Resources