I have placed a csv file in my assets folder for my react app, however, that file is not getting picked up and added to my dist build via webpack (the images are still added as assets to the build but the csv file is not). You can see my webpack build below. So how do I add a csv file to my dist build via webpack (the goal is for users of my app to be able to download this file)? Thanks!
webpack.dev.js
const merge = require('webpack-merge');
const common = require('./webpack.common.js');
const config = merge(common, {
mode: 'development',
devtool: 'inline-source-map',
devServer: {
contentBase: './dist',
historyApiFallback: true,
hot: true,
proxy: {
'/api': {
target: 'http://localhost:5001',
secure: false,
},
},
allowedHosts: [
'localhost',
'fatpandadev'
],
public: 'fatpandadev:8080'
},
});
module.exports = config;
webpack.common.js
const path = require('path');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const DIST_DIR = path.resolve(__dirname, "dist");
const SRC_DIR = path.resolve(__dirname, "src");
const config = {
entry: [
"babel-polyfill",
`${SRC_DIR}/app/index.js`,
`${SRC_DIR}/app/assets/stylesheets/application.scss`,
`${SRC_DIR}/app/components/index.scss`,
"font-awesome/scss/font-awesome.scss",
"react-datepicker/dist/react-datepicker.css",
"rc-time-picker/assets/index.css",
"react-circular-progressbar/dist/styles.css",
"#trendmicro/react-toggle-switch/dist/react-toggle-switch.css",
],
output: {
path: `${DIST_DIR}/app/`,
filename: "bundle.js",
publicPath: "/app/"
},
module: {
rules: [
{
enforce: "pre",
test: /\.js$/,
exclude: /node_modules/,
loader: "eslint-loader",
options: {
failOnWarning: false,
failOnError: true
}
},
{
test: /\.js$/,
include: SRC_DIR,
loader: 'babel-loader',
query: {
presets: ['react', 'stage-2']
}
},
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader'
]
},
{
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'sass-loader'
]
},
{
test: /\.(jpe?g|png|gif|svg)$/i,
loaders: ['file-loader?context=src/images&name=images/[path][name].[ext]', {
loader: 'image-webpack-loader',
query: {
mozjpeg: {
progressive: true,
},
gifsicle: {
interlaced: false,
},
optipng: {
optimizationLevel: 7,
},
pngquant: {
quality: '75-90',
speed: 3,
},
},
}],
exclude: path.resolve(__dirname, "node_modules"),
include: __dirname,
},
{
test: /\.woff2?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
// loader: "url?limit=10000"
use: "url-loader"
},
{
test: /\.(ttf|eot|svg)(\?[\s\S]+)?$/,
use: 'file-loader'
},
{
test: /\.(txt|csv)$/,
use: [
{
loader: 'file-loader',
options: {}
}
]
},
]
},
plugins: [
new MiniCssExtractPlugin({
filename: "application.css"
})
]
};
module.exports = config;
(this answer is only referenced on the server side)
In addition to #PlayMa256,
On Server side(Nodejs runtime), you may need emitFile: true
{
test: /\.(txt|csv|mmdb)$/,
use: [
{
loader: 'file-loader',
options: {
name: "[path][name].[ext]",
emitFile: true,
},
},
],
},
Refer to this PR: https://github.com/webpack-contrib/file-loader/pull/135
In my opinion, file-loader way seem to better than copy-webpack-plugin way.
You can test like below:
import csvPath from './assets/data.csv'
console.log(csvPath) // assets/data.csv
Tested version:
$ cat node_modules/webpack/package.json | jq .version
"4.29.5"
$ cat node_modules/file-loader/package.json | jq .version
"3.0.1"
You might want to check the CopyWebpackPlugin if you have no need to process/parse the files, but only to copy them to your dist folder.
Copy Webpack Plugin
Copies individual files or entire directories to the build directory
Install
npm i -D copy-webpack-plugin
Usage
webpack.config.js
const CopyWebpackPlugin = require('copy-webpack-plugin')
const config = {
plugins: [
new CopyWebpackPlugin([ ...patterns ], options)
]
}
Patterns
A simple pattern looks like this
{ from: 'source', to: 'dest' }
{
test: /\.(txt|csv)$/,
use: [
{
loader: 'file-loader',
options: {}
}
]
}
You should import you csv file as you import your images too.
import your csv files using raw-loader,
{
test: /\.csv$/i,
use: 'raw-loader',
}
Related
I am getting a syntax error in one of my css files from monaco-editor in node_modules. It is an unknown word error:
> 1 | // Imports
| ^
2 | import ___CSS_LOADER_API_IMPORT___ from "../../../../../../css-loader/dist/runtime/api.js";
3 | var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(function(i){return i[1]});
# ./node_modules/monaco-editor/esm/vs/platform/contextview/browser/contextMenuHandler.css 2:12-317 9:17-24 13:15-29
However, I have css-loader configured in my webpack.config.js:
const HtmlWebPackPlugin = require("html-webpack-plugin");
const PerspectivePlugin = require("#finos/perspective-webpack-plugin");
const path = require("path");
const plugins = [
new HtmlWebPackPlugin({
title: "Perspective React Example",
template: "./src/frontend/index.html",
}),
new PerspectivePlugin(),
];
module.exports = {
context: path.resolve(__dirname),
entry: "./src/frontend/index.tsx",
mode: "development",
devtool: "source-map",
resolve: {
extensions: [".ts", ".tsx", ".js"],
},
plugins: plugins,
module: {
rules: [
{
test: /\.ts(x?)$/,
//exclude: /node_modules/,
loader: "ts-loader",
},
{
test: /\.css$/,
//exclude: /node_modules/,
use: [
"style-loader",
{
loader: "css-loader",
options: {
importLoaders: 1,
},
},
'postcss-loader'
],
},
],
},
devServer: {
// superstore.arrow is served from here
contentBase: [
path.join(__dirname, "dist"),
path.join(__dirname, "node_modules/superstore-arrow"),
],
},
experiments: {
executeModule: true,
syncWebAssembly: true,
asyncWebAssembly: true,
},
output: {
filename: "app.js",
path: __dirname + "/dist",
},
};
I also have a config file for postcss-loader:
module.exports = {
plugins: [
require('autoprefixer')
]
};
I'm not sure what is wrong with what I'm doing, so I'm wondering if there is another loader I need to add to webpack.config.js or if my configuration is incorrect?
I had same issue, try this:
use: [
"style-loader",
"css-loader",
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [
[
"postcss-preset-env",
{
// Options
},
],
],
},
},
},
],
Below is the webpack config code and it's size is around 6.2 MB. In production mode it looks more time load the signin page url and from second time onwards it looks good , the problem with first time and need suggestion to reduce the bundle.js file size
webpack.base.js
module.exports = {
//Running babel to every file
module: {
rules: [
{
test: /\.js?$/,
loader: 'babel-loader',
exclude: /node_modules/,
options: {
presets: [
'react',
'stage-0',
['env', { targets: { browsers: ['last 2 versions'] } }]
]
}
}, {
test: /\.css$/,
loader: "style-loader!css-loader"
},
{
test: /\.less$/,
use:[
{
loader: "style-loader"
},
{
loader: 'css-loader'
},
{
loader: "less-loader"
}
]
},
{
test: /\.(jpe?g|png|gif|woff|woff2|eot|ttf|svg|otf)(\?[a-z0-9=.]+)?$/,
loader: 'url-loader?limit=100000'
}
]
}//end module
}
webpack.client.js:
const config = {
entry: './src/client/client.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'public')
}
};
module.exports = merge(baseConfig, config)
webpack.server.js:
const server_config = {
//letting webapck know that this bundle is created for node server.
target: 'node',
entry: './src/server/server.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'build')
},
externals: [webpackNodeExternals()],
node:{
__dirname:false
}
};
module.exports = merge(baseConfig, server_config);
Here is how I optimize webpack. You can view my full config here
First you need to run webpack production mode when you want to build in production
webpack -p --mode=production
Below is minial config
const path = require("path");
const webpack = require("webpack");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CompressionPlugin = require("compression-webpack-plugin");
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
const WebpackShellPlugin = require('webpack-shell-plugin');
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
new UglifyJsPlugin({ // minify js file
cache: true,
parallel: true,
sourceMap: false,
extractComments: 'all',
uglifyOptions: {
compress: true,
output: null
}
}),
new OptimizeCSSAssetsPlugin({ // minify css
cssProcessorOptions: {
safe: true,
discardComments: {
removeAll: true,
},
},
})
]
},
plugins: [
new CompressionPlugin({ // gzip js and css
test: /\.(js|css)/
}),
new UglifyJsPlugin(), // uglify js
new WebpackShellPlugin({
onBuildStart: ['echo "Starting postcss command"'],
onBuildEnd: ['postcss --dir wwwroot/dist wwwroot/dist/*.css'] // uglify css using postcss
})
],
module: {
rules: [{
test: /\.scss$/,
use: [
'style-loader',
MiniCssExtractPlugin.loader,
{
loader: "css-loader",
options: {
minimize: true,
sourceMap: true
}
},
{
loader: "sass-loader"
}
]
},
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
loader: ["babel-loader", "eslint-loader"]
},
{
test: /\.(jpe?g|png|gif)$/i,
loader: "file-loader"
},
{
test: /\.(woff|ttf|otf|eot|woff2|svg)$/i,
loader: "file-loader"
}
]
}
};
I am developing a site and using webpack for obvious reasons. The problem I am having is with path resolution for images which are imported into my project via my SCSS files. The issue is that css-loader isn't resolving the correct path. What seems to be happening is the following:
If I allow css-loader to handle the url() imports (leaving the url option to true) it rewrites the file path relative to the output directory specified in ExtractCSSChunksPlugin(), for example:
url('../img/an-image.jpg') should be rewritten to url('http://localhost:3000/assets/img/an-image.jpg'), however, what is actually being outputted is url('http://localhost:3000/assets/css/assets/img/an-image.jpg').
If I change it to false the correct path is resolved but the file-loader isn't able to find the images and then emit them.
I know that the images are being outputted when the css-loader is handling url resolution as I can see the emitted message when the bundle is compiled -- it does not fail.
I can also get the images to display if I manually add import calls to them in the JS entry point, set in the entry: field, and then call the absolute path in SCSS. But this is not desirable as it becomes tedious with the growing project.
I have tried to use resolve-url-loader and changing multiple settings but I just can't seem to get this to work.
I have also tried using the resolve: { alias: { Images: path.resolve(__dirname, 'src/assets/img/' } } option provided by webpack and then calling url('~Images/an-image.jpg') in my SCSS but it just reproduces the same results.
So, overall, my issue is that I need to be able to use relative paths in my SCSS and then have them rewritten to the correct path by one of my loaders.
My current webpack config (outputting the files with file loader but prepending assets/css/ to the start of the url) is as follows:
"use strict";
const webpack = require('webpack');
const merge = require('webpack-merge');
const common = require('./webpack.common');
const ExtractCSSChunksPlugin = require('extract-css-chunks-webpack-plugin');
module.exports = merge(common, {
mode: 'development',
devtool: 'inline-source-map',
entry: [
'webpack-hot-middleware/client',
],
module: {
rules: [
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['#babel/preset-env'],
}
}
},
{
test: /\.scss$/,
use: [
{
loader: ExtractCSSChunksPlugin.loader,
options: {
hot: true,
}
},
{
loader: 'css-loader',
options: {
sourceMap: true,
}
},
{
loader: 'sass-loader',
options: {
sourceMap: true,
}
}
]
},
{
test: /\.html$/,
use:['html-loader']
},
{
test:/\.(svg|jpg|png|gif)$/,
use: [{
loader:'file-loader',
options: {
publicPath: 'assets/img',
outputPath: 'assets/img',
name: '[name].[ext]',
esModule: false
}
}],
},
]
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new ExtractCSSChunksPlugin({
filename: 'assets/css/[name].css',
chunkFilename: 'assets/css/[id].css',
}),
]
});
Thank you in advance.
Ok, so it seems I have fixed the issue by resolving the publicPath set in the file loader config field: publicPath: path.resolve(__dirname, '/assets/img').
My config is now:
"use strict";
const webpack = require('webpack');
const merge = require('webpack-merge');
const common = require('./webpack.common');
const path = require('path');
const ExtractCSSChunksPlugin = require('extract-css-chunks-webpack-plugin');
module.exports = merge(common, {
mode: 'development',
devtool: 'inline-source-map',
entry: [
'webpack-hot-middleware/client',
],
module: {
rules: [
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['#babel/preset-env'],
}
}
},
{
test: /\.scss$/,
use: [
{
loader: ExtractCSSChunksPlugin.loader,
options: {
hot: true,
}
},
{
loader: 'css-loader',
options: {
sourceMap: true,
}
},
{
loader: 'sass-loader',
options: {
sourceMap: true,
}
}
]
},
{
test: /\.html$/,
use:['html-loader']
},
{
test:/\.(svg|jpg|png|gif)$/,
use: [{
loader:'file-loader',
options: {
publicPath: path.resolve(__dirname, '/assets/img'),
outputPath: 'assets/img',
name: '[name].[ext]',
esModule: false
}
}],
},
]
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new ExtractCSSChunksPlugin({
filename: 'assets/css/[name].css',
chunkFilename: 'assets/css/[id].css',
}),
]
});
I think adding url loader in the webpack configuration would help.
{
test: /\.(jpg|png)$/,
use: {
loader: "url-loader",
options: {
limit: 25000,
},
},
},
I'm having issues with setting up web-pack 4 and svg-sprite-loader to render svg icons as background images. I was following these instructions from official docs for svg-sprite-loader (https://github.com/kisenka/svg-sprite-loader/tree/master/examples/extract-mode).
I have successfully managed to create sprite.svg file in my dist folder and use it as reference for my use tags inside of html. However, i was also trying to use svg icons from my src/images/icons folder for a background image like this:
background: url('../images/icons/upload_icon.svg') 10% 50% no-repeat;
when doing this, webpack compiles correctly, but creates this in dist css file:
background: url([object Module]) 10% 50% no-repeat;
Any help would be great.
here is my webpack config file:
const path = require("path");
const webpack = require("webpack");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CleanWebpackPlugin = require("clean-webpack-plugin");
const SpriteLoaderPlugin = require("svg-sprite-loader/plugin");
module.exports = {
mode: "development",
devtool: "source-map",
output: {
filename: "bundle.js",
path: path.resolve(__dirname, "dist")
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
sourceMap: true
}
}
},
{
// scss configuration
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: "css-loader"
},
{
loader: "postcss-loader"
},
{
loader: "sass-loader",
options: {
sourceMap: true
}
}
]
},
{
// html configuration
test: /\.html$/,
use: {
loader: "html-loader"
}
},
{
// images configuration
test: /\.(jpg|jpeg|gif|png|woff|woff2)$/,
use: [
{
loader: "file-loader",
options: {
name: "[path][name].[ext]"
}
}
]
},
{
test: /\.svg$/,
use: [
{
loader: "svg-sprite-loader",
options: {
extract: true,
spriteFilename: "sprite.svg"
}
}
]
}
]
},
plugins: [
// all plugins used for compiling by webpack
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
title: "Style Guide",
template: path.resolve(__dirname, "src", "index.html")
}),
new MiniCssExtractPlugin({
filename: "app.css"
}),
new SpriteLoaderPlugin()
]
};
Adding esModule: false to the file-loader options did the trick for me.
{
test: /\.(jpg|png|gif|svg)$/,
use: {
loader: 'file-loader',
options: {
name: "[name].[ext]",
outputPath: "img",
esModule: false
}
},
You have to pass esModule: false for svg-sprite-loader options.
By the way (it is not related to esModule): With MiniCssExtractPlugin you can not to extract svg sprite. I've faced this problem one hour ago..
After a few hours, I have managed to make this thing to work, thanks to #WimmDeveloper for pointing me in right direction. Main change from prior webpack config file is that I have added esModule: false in svg-sprite-loader options and replaced MiniCssExtractPlugin with extract-text-webpack-plugin. Mind you that this solution is not ideal since this webpack plugin is deprecated.
here is my full webpack config file:
const path = require("path");
const webpack = require("webpack");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const CleanWebpackPlugin = require("clean-webpack-plugin");
const SpriteLoaderPlugin = require("svg-sprite-loader/plugin");
const ExtractTextPlugin = require("extract-text-webpack-plugin");
module.exports = {
mode: "development",
devtool: "source-map",
output: {
filename: "bundle.js",
path: path.resolve(__dirname, "dist")
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
sourceMap: true
}
}
},
{
test: /\.(s*)css$/,
use: ExtractTextPlugin.extract({
use: ["css-loader", "postcss-loader", "sass-loader"]
})
},
{
// html configuration
test: /\.html$/,
use: {
loader: "html-loader"
}
},
{
test: /\.svg$/,
use: [
{
loader: "svg-sprite-loader",
options: {
esModule: false,
extract: true,
spriteFilename: "sprite.svg"
}
}
]
},
{
// files configuration
test: /\.(jpg|jpeg|gif|png|woff|woff2)$/,
use: [
{
loader: "file-loader",
options: {
name: "[path][name].[ext]"
}
}
]
}
]
},
plugins: [
// all plugins used for compiling by webpack
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
title: "Style Guide",
template: path.resolve(__dirname, "src", "index.html")
}),
new ExtractTextPlugin({ filename: "app.css" }),
new SpriteLoaderPlugin()
]
};
I want to use sass stylesheets that are organized with each of my react components, like this:
components/
|- componentOne
|- componentOne.js
|- componentOne.scss
|- componentTwo
|- componentTwo.js
|- componentTwo.scss
|- componentThree
|- componentThree.js
|- componentThree.scss
Are there any webpack settings / tools that will automatically load and compile all .scss files in a certain directory?
EDIT:
So the below is the current webpack config that I am using (written from a previous developer). I added in the line line in entries of SRC_DIR + "/app/components/", so that extract-text-webpack-plugin will pick up all of the .scss files in the components directory. But when I try to run the build I get the following error message. What am I doing wrong? Thanks.
ERROR in multi babel-polyfill ./src/app/index.js ./src/app/assets/stylesheets/application.scss ./src/app/components/ font-awesome/scss/font-awesome.scss react-datepicker/dist/react-datepicker.css rc-time-picker/assets/index.css react-circular-progressbar/dist/styles.css #trendmicro/react-toggle-switch/dist/react-toggle-switch.css
Module not found: Error: Can't resolve '/Users/user123/dev/project/src/app/components/' in '/Users/user123/dev/project'
# multi babel-polyfill ./src/app/index.js ./src/app/assets/stylesheets/application.scss ./src/app/components/ font-awesome/scss/font-awesome.scss react-datepicker/dist/react-datepicker.css rc-time-picker/assets/index.css react-circular-progressbar/dist/styles.css #trendmicro/react-toggle-switch/dist/react-toggle-switch.css
Webpack config:
const path = require('path');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const DIST_DIR = path.resolve(__dirname, "dist");
const SRC_DIR = path.resolve(__dirname, "src");
const config = {
entry: [
"babel-polyfill",
SRC_DIR + "/app/index.js",
SRC_DIR + "/app/assets/stylesheets/application.scss",
SRC_DIR + "/app/components/",
"font-awesome/scss/font-awesome.scss",
"react-datepicker/dist/react-datepicker.css",
"rc-time-picker/assets/index.css",
"react-circular-progressbar/dist/styles.css",
"#trendmicro/react-toggle-switch/dist/react-toggle-switch.css",
],
output: {
path: DIST_DIR + "/app/",
filename: "bundle.js",
publicPath: "/app/"
},
devtool: 'inline-source-map',
devServer: {
contentBase: './dist',
historyApiFallback: true,
hot: true,
proxy: {
'/api': {
target: 'http://localhost:5001',
secure: false,
},
}
},
module: {
rules: [
{
enforce: "pre",
test: /\.js$/,
exclude: /node_modules/,
loader: "eslint-loader",
options: {
failOnWarning: false,
failOnError: true
}
},
{
test: /\.js$/,
include: SRC_DIR,
loader: 'babel-loader',
query: {
presets: ['react', 'stage-2']
}
},
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
use: 'css-loader?importLoaders=1',
})
},
{
test: /\.scss$/,
use: ExtractTextPlugin.extract(['css-loader', 'sass-loader']),
},
{
test: /\.(jpe?g|png|gif|svg)$/i,
loaders: ['file-loader?context=src/images&name=images/[path][name].[ext]', {
loader: 'image-webpack-loader',
query: {
mozjpeg: {
progressive: true,
},
gifsicle: {
interlaced: false,
},
optipng: {
optimizationLevel: 7,
},
pngquant: {
quality: '75-90',
speed: 3,
},
},
}],
exclude: path.resolve(__dirname, "node_modules"),
include: __dirname,
},
{
test: /\.woff2?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
// loader: "url?limit=10000"
use: "url-loader"
},
{
test: /\.(ttf|eot|svg)(\?[\s\S]+)?$/,
use: 'file-loader'
},
]
},
plugins: [
new ExtractTextPlugin({
filename: "application.css",
allChunks: true
})
]
};
module.exports = config;
In order to compile your scss, webpack has to know about it. In order to let him know, you just import those scss files in your current component.
Now, what lasts you is to configure webpack. You are going to use sass-loader, css-loader and style-loader.
module.exports = {
entry: './src/',
module: {
rules: [
{
test: /\.scss$/,
use: [
'style-loader',
'css-loader',
'sass-loader'
]
}
]
}
}
This is the most basic config that can be done.
If you want to have your compiled css into files, just use Mini-css-extract-plugin
module: {
{
test: /\.scss$/,
loaders: [
'style-loader',
'css-loader',
'sass-loader'
]
},
{
test: /\.less$/,
loaders: [
'style-loader',
'css-loader',
'less-loader'
]
},
{
test: /\.css$/,
loaders: [
'style-loader',
'css-loader'
]
},
},
},
resolve: {
extensions: [ '.css', '.scss'],
}