Webpack unable to get json file - json

I am new to Webpack and I am having a hard time to understand how I can access the content of my json file being added in entry and loaded using json-loader:
entry :
en: {
`${config.basePaths.tmp}script.js`,
`${config.basePaths.tmp}en.json`
}
},
output: {
publicPath: '/js/',
path: `${config.paths.scripts.dist}`,
filename: `[name].script.js`
},
module: {
loaders: [
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
loader: 'babel-loader',
query: {
presets: ['es2015']
}
},
{
test: /\.coffee$/,
loader: 'coffee-loader'
},
{
test: /\.json$/,
loader: 'json-loader'
}
]
}
The object is added to my output file (en.script.js) but I have no clue how to access it... It looks like this:
function(module, exports) {
module.exports = {
"en": {
"title": "I love webpack",
"something": "else"
}
};
}
Please help me.

You should not put a JSON file as the entry point. Entry points are meant to be the starting point of your app and if you specify multiple files per entry point it's just to include them in the same bundle, but they don't really interact with each other (see Concepts - Entry Points).
Instead with webpack you can import files that are not JavaScript, such as .json, and if you have an appropriate loader it will turn that into valid JavaScript which you can use just as any other JavaScript you import. So in your script.js (your entry point) you can import the JSON with:
import enJson from './en.json';
Now you can use enJson as you want, which contains the JavaScript representation of en.json. And by the way remove that from your entry, because webpack will figure out which files are used by looking what is imported from your entry point (and all its dependencies).
entry : {
en: `${config.basePaths.tmp}script.js`,
},

Related

File-loader creating 2 images and linking the wrong one

file-loader is creating two separate images in my build folder. One is the named correctly and saved in the correct path, the other is named [hash].png (which is the default) and is stored in build, not build/images. The second incorrect file is 0 bytes; this is the one being linked in the final index.html file in the build folder. I've defined both outputPath and publicPath. publicPath doesn't seem to actually do anything though, regardless of what I put there. Am I misunderstanding what it does?
module.exports = {
entry: {
index: './app/main.js',
vendor: './app/vendor.js'
},
output: {
path: path.resolve(__dirname, './build'),
filename: '[name].[contenthash].js',
},
module: {
rules: [
{
test: /\.js$/,
exclude: [/node_modules/, /api/, /tests/, /coverage/],
use: 'babel-loader'
},
{
test: /\.scss$/,
use: ['style-loader', 'css-loader', 'sass-loader']
},
{
test: /\.html$/,
use: 'html-loader'
},
{
test: /\.(svg|png|jpg|gif)$/,
use:{
loader: 'file-loader',
options: {
name: '[name].[hash].[ext]',
outputPath: 'images/',
publicPath: 'images/'
}
}
},
]
},
plugins: [
new HtmlWebpackPlugin({ template: './app/index.html' }),
new CleanWebpackPlugin()
]
};
Image link in final html:
<img src="465107fe07e3ec18a463.png">
Another post with the same issue that didn't get any answers:
Webpack, I am trying to use file loader to load images but whenever i run build i get 2 images not 1 and the one linking to the html file is wrong
I eventually figured it out. As of Webpack 5.0, this can be handled without installing a loader at all. So file-loader, url-loader, raw-loader, etc. are now obsolete.
https://webpack.js.org/guides/asset-modules/
This is a problem of file-loader v6.
I solved this with the way adding esModule option.
Both html-loader, css-loader and loader that using image url need the esModule option false.
Or you should use the file-loader except v6.
{
loader: 'css-loader',
options: {
esModule: false
}
},
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: 'asset/resource',
},

Gatsby JSON loader not following refs

I need to dereference (swap out JSON References) when importing JSON or YAML files directly into Gatsby pages. Gatsby is pretty good at importing JSON files directly (probably due to some underlying webpack loader), but it doesn't seem to handle JSON refs, a lá "$ref": "../something.json.
For example:
parent.json
{
"someRef" {
"$ref": "./child.json"
}
}
child.json
{
"foo": "bar"
}
index.js
import {SomeJson} from './parent.json'
console.log(SomeJson)
// Expected output: {someRef: {foo: bar}}
// Actual output: {someRef: {$ref: './child.json'}}
I figured that perhaps the default JSON loader being used by Gatsby doesn't allow for JSON References. Fine. But couldn't the webpack configuration be extended to try and add this functionality? Here's my attempt:
gatsby-node.js
exports.onCreateWebpackConfig = ({ actions }) => {
actions.setWebpackConfig({
module: {
rules: [
{
test: /\.json$/,
use: [
{
loader: '#cloudflare/json-schema-ref-loader'
}
]
}
]
},
})
}
The #cloudflare/json-schema-ref-loader library is a webpack loader designed to follow refs. so I figured this could be used.
When running gatsby develop, the build fails with:
Unexpected token m in JSON at position 0 while parsing near 'module.exports = {
...'
error Generating development SSR bundle failed
Any help would be greatly appreciated.

Have problem with importing image in react

Hello everyone I have some problems with importing images to my project. I tried before to import image on my old project the way that i did was working but not for that time. I imported image like:
import Fav from '../img/fav.png'
My file path is in src/img/fav.png and I'm trying to import from src/components/App.jsx
So the error I have is :
ERROR in ./img/fav.png 1:0
Module parse failed: Unexpected character '�' (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)
# ./components/App.jsx 3:0-33
# ./entry.jsx
# multi ./entry.jsx
I tried to find some solutinons in the web bu i couldn't find.
Thanks for help
You need a webpack loader to load the image, e.g. file-loader:
{
test: /\.(png|jpg|gif|svg)$/,
use: [
{
loader: 'file-loader',
options: {
outputPath: 'images',
},
},
],
},
The solution was here:
{
test: /\.(png|svg|jpg|gif)$/,
include: path.resolve(__dirname, 'src/assets'),
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]'
}
}
]
}
The path is included by default.

Webpack - Yaml -> JSON -> Extract file

I have a YAML file with a few translations. I need to transform these files into a JSON file. I've tried using yaml-import-loader and json-loader but I get an error.
Here's my setup:
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const extractEnglish = new ExtractTextPlugin('lang/en.js');
module.exports = {
entry: [
'./src/locales/application.en.yml',
],
output: {
filename: 'english.js',
},
module: {
strictExportPresence: true,
rules: [
{
test: /\.en\.yml$/,
use: extractEnglish.extract({
use: [
// { loader: 'json-loader' },
{
loader: 'yaml-import-loader',
options: {
output: 'json',
},
}],
}),
},
],
},
plugins: [
extractEnglish,
],
};
And the error I get:
Users/xxx/Documents/Project/node_modules/extract-text-webpack-plugin/dist/index.js:188
chunk.sortModules();
^
TypeError: chunk.sortModules is not a function
at /Users/xxx/Documents/Project/node_modules/extract-text-webpack-plugin/dist/index.js:188:19
Same error whether or not the json-loader is commented or not.
I really don't understand what is going wrong.
Versions:
"webpack": "2.6.1",
"extract-text-webpack-plugin": "^3.0.0",
"json-loader": "^0.5.7",
Not sure if this will help your situation but I recently found a solution to my i18n loading problem. I do this to extract YAML into JSON files upfront as I use angular-translate and needed to load files dynamically and on-demand. I avoid extract-text-webpack-plugin and use only loaders: file-loader and yaml-loader.
First I setup the import of my .yaml files near the beginning of source (in my case a specific chain of import files for webpack to process)
import "./i18n/en.user.yaml";
I updated webpack config to translate YAML to JSON and have it available to load dynamically (everything originates from my 'src' directory, hence the context):
rules: [{
test: /.\.yaml$/,
use: [{
loader: 'file-loader',
options: {
name: '[path][name].json',
context: 'src'
}
},{
loader: 'yaml-loader'
}]
}]
This will translate my yaml file(s) and export them to my public directory, in this case at '/i18n/en.user.json'.
Now when angular-translate uploads my configured i18n settings via $http on-demand, it already has the parsed YAML and avoids having to parse it with js-yaml (or similar) on the front end.
A relatively old question, but I found it while searching for a solution to the same problem, so I thought it worth to chip in.
If you're not really using translation files in your code (i.e. you never import and use them directly) then using a Webpack loader is not the most elegant solution (you'd be forced to import them just so that the loader could be triggered and perform the conversion).
An alternative would be to use the CopyWebpackPlugin instead: it supports a transform option, which takes a function receiving the content of the file as a Buffer.
With a YAML parser (like js-yaml) as an additional dependency, adding this to your Webpack configuration would work:
const yaml = require('js-yaml');
const CopyWebpackPlugin = require('copy-webpack-plugin');
module.exports = {
// OTHER WEBPACK CONFIG HERE
plugins: [
new CopyWebpackPlugin({
patterns: [
{
from: 'i18n/**/*',
to: 'i18n/[name].json',
transform(content) {
return Buffer.from(
JSON.stringify(
yaml.load(content.toString('utf8'), {
schema: yaml.JSON_SCHEMA
})
),
'utf8'
)
}
}
]
})
]
}
The i18n folder in the above example would contain your .yml translations.
The Copy plugin would load them, convert them to JSON, and save them in the output folder under i18n/ (as specified by the to option).

Copy multiple html files with webpack2 (from src to dist folder)

Which loader/plugin should I use to move multiple html files from one folder (src) to another (dist) which only imports files that obey certain rules in this example I need to import multiple html files, so the regex would be:
/.html$/
I know that I can move html using html-webpack-plugin but I don't want to create object instance for every page I want to move. I also don't want to make multiple imports in my app.js (entry point for webpack).
So i tried with copy-webpack-plugin but this one moves everything from src to dist. Is it possible to filter with my regex pattern or do you know other way that works to do this?
new CopyWebpackPlugin([{
from: './src',
to: path.resolve(__dirname, "dist")
}],
I gues that I could use system
mkdir dist && cp ./src/*.html ./dist
And simply run this in my package.json in the script before running webpack -d
but this is not the "polite" way of doing this. I'm sure that webpack can do that easily..
Ps. Also, it would be nice to minimize those files, if possible.
Moving all files in batch
So for now it works like this. To not have to include every single file from the src folder in to my app.js (which is my entry point for webpack) I required all files using require.context()
Because my app.js is also in my src folder I use relative path to require all other file:
// requires all files in current directory and sub directories
require.context("./", true, /^\.\/.*\..*/);
Or if you want to import files with certain extension sue this instead:
// requires all html files in current directory and sub directories
require.context("./", true, /^\.\/.*\.html/);
So now everything is imported and I don't have to require files manually. The only thing I have to do is set entry to app.js using path.resolve.
I now can use test property to get what I want from within in webpack.config.js module rules.
...
module: {
rules: [
{
test: /\.(html)$/,
use:
[
{
loader: 'file-loader',
options: {
name: '[path][name].[ext]',
context: './src',
outputPath: '/',
publicPath: '/'
}
},
...
This works fine my files are moved (but not minified). Perhaps someone can take this a little bit further and the answer will be completed.
Below i place full file for reference only
webpack.config.js
// imports node plugin which allows us to save data to a file for example css external files
var ExtractTextPlugin = require("extract-text-webpack-plugin");
// cleans defined folders before webpack will build new files now we can remove package.json commands "rm -rf ./dist && ..."
var CleanWebpackPlugin = require("clean-webpack-plugin");
// copies to memory html from template file and injects css and javascript as well as img src to newly generated html file.
var HtmlWebpackPlugin = require("html-webpack-plugin");
// to include jquery we need to import 'jquery' in app.js but also we need to make connection between bundle.js jquery script
var Webpack = require('webpack');
// includes node path resover that is need for webpack-dev-server to run properly
var path = require('path');
// webpack configuration
module.exports = {
entry: [
path.resolve(__dirname, "src/app.js"),
],
output: {
path: path.resolve(__dirname, 'dist'), // defins the main utput directory
filename: 'js/bundle.js',
},
devServer: {
contentBase: path.join(__dirname, "dist"),
compress: true,
port: 8080,
},
module: {
rules: [
{
test: /\.(html)$/,
use:
[
{
loader: 'file-loader',
options: {
name: '[path][name].[ext]',
context: './src',
outputPath: '/',
publicPath: '/'
}
},
]
},
{
test: /\.(jpg|png|gif)$/,
use: {
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'img/',
publicPath: '/' // this path relates to reference path from the index.html file that imports out bundle.js file
}
}
},
{
test: /\.js$/,
use: [
{
loader: 'babel-loader',
options: {
presets: ['es2015']
}
}
]
},
{
test: /\.sass$/,
include: [
path.resolve(__dirname, "src/sass")
],
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
//resolve-url-loader may be chained before sass-loader if necessary
use: [
{
loader: 'css-loader',
options: {
minimize: false,
sourceMap: true,
}
},
'sass-loader'
]
})
},
]
},
plugins: [
// mapping jQuery variable to our node module dependency (remember to import 'jquery' in app.js)
// below we make jquery available as both the $ and jQuery variable
new Webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery'
}),
// use extract plugin to build an external file loded by sass-loader > complied to css > movig to bundle.css
new ExtractTextPlugin({
filename: 'css/bundle.css'
}),
// remove all files from this folder before generating new files
// new CleanWebpackPlugin(['dist']),
],
}
You should be able to use copy-webpack-plugin's support for globs to achieve what you want.
new CopyWebpackPlugin([
{
from: './src/*.html',
to: path.resolve(__dirname, 'dist')
}
])
The globs accept minimatch options too.
EDIT:
In addition, if you're copying just HTML (and want to minify them), you might want to take a look at html-webpack-plugin. The minify option allows you to minify those HTML files.