Add a specific node module in webpack bundle - javascript

I have added one of Bulma extensions in my react project
https://wikiki.github.io/components/quickview/
To use it I have installed it using npm & extension requires to add below line when DOM is completely loaded, so I added it in componentDidMount
var quickviews = bulmaQuickview.attach();
and below line in my index.html
<script type="text/javascript" src="/node_modules/bulma-extensions/bulma-quickview/dist/js/bulma-quickview.min.js"></script>
I am using webpack to bundle & have excluded all node modules from bundle.
Problem : In development environment for webpack it works fine but after bundling for production it gives me error that
bulmaQuickview is not defined
How can I bundle a specific node module in my webpack bundle? and what will be the correct reference to add.
Webpack config
module.exports = {
target: 'web',
entry: "./index.js",
output: {
filename: "bundle.js"
},
devtool: 'eval-source-map',
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: "css-loader"
})
},
{
test: /\.(png|jpg)$/,
use: [{
loader: 'url-loader',
options: {
limit: 8000, // Convert images < 8kb to base64 strings
name: 'images/[hash]-[name].[ext]'
}
}]
},
{
test: /\.(png|svg|jpg|gif)$/,
include: path.join(__dirname, 'dist/image'),
loader: 'file-loader'
}
]
},
plugins: [new WebpackNotifierPlugin(), new BrowserSyncPlugin(), new ExtractTextPlugin("styles.css"),
new webpack.DefinePlugin({
'API_URL': API_URL[environment]
})
]
};

You're adding it to the index.html so webpack isn't bundling it. Have you tried importing it into the same js file that it is used in? Either that or add it to your entry property after index.html (make it an array).

Related

Webpack not building because CssSyntaxError

I am trying to run a webpack-dev-server built, but it fails everytime with the following error:
ERROR in ./src/style.css (./node_modules/css-loader/dist/cjs.js!./node_modules/style-loader/dist/cjs.js!./node_modules/css-loader/dist/cjs.js!./src/style.css)
Module build failed (from ./node_modules/css-loader/dist/cjs.js):
CssSyntaxError
(1:1) Unknown word
> 1 | var api = require("!../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js");
| ^
2 | var content = require("!!../node_modules/css-loader/dist/cjs.js!./style.css");
3 |
My webpack.dev.js looks like this:
const path = require('path');
const { merge } = require('webpack-merge');
const common = require('./webpack.common.js');
module.exports = merge(common, {
entry: './src/index.js',
mode: 'development',
devtool: 'inline-source-map',
optimization: {
usedExports: true,
},
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
module: {
rules: [
{
test: /\.css$/,
use: [
'style-loader',
'css-loader',
],
},
{
test: /\.(png|svg|jpg|gif)$/,
use: [
'file-loader',
],
},
{
test: /\.m?js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['#babel/preset-env']
}
}
},
],
},
});
The error appears on using this in my index.js:
import './style.css';
Many solutions suggest the order of the style-loader and the css-loader, but as far as I know it is in the correct order. What am I doing wrong?
I had the same error when trying to use the style-loader and the MiniCssExtractPlugin simultaneously. Your example uses webpack merge, so I assume that you also have a webpack.common.js somewhere with additional CSS rules?
In my case, what solved it was as following:
I have the following rules in my webpack.dev.config.js:
module: {
rules: [
{
test: /\.(sass|scss)$/,
use: [
"style-loader",
"css-loader",
"postcss-loader",
{
loader: "sass-loader",
options: {
// Prefer `dart-sass`
implementation: require("sass"),
},
},
],
},
],
},
And the following in my webpack.prod.config.js:
module: {
rules: [
{
test: /\.(sass|scss)$/,
use: [
MiniCssExtractPlugin.loader,
"css-loader",
"postcss-loader",
{
loader: "sass-loader",
options: {
// Prefer `dart-sass`
implementation: require("sass"),
},
},
],
},
],
},
You could also use the ternary operator to check if mode === 'production' and leave it in one file but I prefer to have two separate files to keep it more readable in case the webpack configs get too big.
I also tried to move the css-loader, postcss-loader and sass-loader to the same webpack.common.js file but for some reason it didn't work.
Not sure if that might be cause of your error but it fixed it in my use case so now I use the style loader for my dev environment and the plugin to compile for production.
This worked for webpack 5 and node 16

Custom less-loader in Laravel Mix

I am trying to import LESS file in my JS code.
But I get error like - 'You may need an appropriate loader to handle this file type.'.
Version - "laravel-mix": "^0.11.4"
In my webpack.mix.js I tried this code
mix.webpackConfig({
module: {
rules: [{
test: /\.less$/,
loader: ['style-loader','css-loader','less-loader']
}]
}
})........
But I still getting the same error.
const path = require('path');
mix.webpackConfig({
module: {
rules: [
{
test: /\.less$/,
loader: "style-loader!css-loader!less-loader",
exclude: [
path.resolve(__dirname, "node-modules"),
path.resolve(__dirname, "resources/assets/less"),
],
},
]}
})
Works for my issue

how to ready react app with webpack

I'm new to React and Webpack and all this stuff. I've created a React app with Webpack and I used webpack-dev-server to create and debug my app.
So in my webpack.config.js file I have this code:
var debug = process.env.NODE_ENV !== "production";
var webpack = require('webpack');
var path = require('path');
const ExtractTextPlugin = require("extract-text-webpack-plugin");
module.exports = {
context: path.join(__dirname, "src"),
devtool: debug ? "inline-sourcemap" : false,
entry: "./js/client.js",
module: {
loaders: [
{
test: /\.js?$/,
exclude: /(node_modules|bower_components)/,
loader: 'babel-loader',
query: {
presets: ['react', 'es2015', 'stage-0'],
plugins: ['react-html-attrs', 'transform-decorators-legacy', 'transform-class-properties'],
}
},
{
test: /\.scss$/,
use: debug ? [{
loader: "style-loader" // creates style nodes from JS strings
}, {
loader: "css-loader" // translates CSS into CommonJS
}, {
loader: "sass-loader" // compiles Sass to CSS
}] : ExtractTextPlugin.extract({ fallback: "style-loader", use: "css-loader" })
}
]
},
output: {
path: __dirname + "/src/",
filename: "client.min.js"
},
plugins: debug ? [] : [
new ExtractTextPlugin('style.min.css'),
new webpack.optimize.DedupePlugin(),
new webpack.optimize.OccurrenceOrderPlugin(),
new webpack.optimize.UglifyJsPlugin({ mangle: false, sourcemap: false }),
],
externals: {
"jquery": "jQuery",
"react": "React",
"react-dom": "ReactDOM",
"animejs": "anime"
}
};
When I use webpack-dev-server --content-base src --inline --hot, I see my app working in localhost:8080 but now I want to make the app ready for production. so I ran these codes in my terminal:
$: NODE_ENV=production
$: webpack
It doesn't change anything! So first question: what is wrong with NODE_ENV=production? When I change the first line of my webpack to var debug = process.env.NODE_ENV === "production"; //false it works.
There are other problems!
I'm using sass and When debug === false and I open my index.html file in browser, my styles aren't compiled! Just all of my sass code is copied to style.min.css file The problem should be with this part of code:
{
test: /\.scss$/,
use: debug ? [{
loader: "style-loader" // creates style nodes from JS strings
}, {
loader: "css-loader" // translates CSS into CommonJS
}, {
loader: "sass-loader" // compiles Sass to CSS
}] : ExtractTextPlugin.extract({ fallback: "style-loader", use: "css-loader" })
}
And the last problem is with absolute paths! I have this code in my app:
<img src="/images/avatar.jpg">
It works when I use webpack-dev-server but when I use webpack, the image is not found as it tries to open it from the root of my linux.
So these are my questions:
why NODE_ENV=production doesn't work?
How should I compile sass and put the css in style.min.css?
How can I use absolute paths in my app?
thanks in advance
How should I compile sass and put the css in style.min.css?
Try following config
{
test: /\.scss$/,
use: debug ? [{
loader: "style-loader" // creates style nodes from JS strings
}, {
loader: "css-loader" // translates CSS into CommonJS
}, {
loader: "sass-loader" // compiles Sass to CSS
}] : ExtractTextPlugin.extract({
fallback: "style-loader",
use: [
{
loader: "css-loader",
options: {
modules: true,
},
},
{
loader: "sass-loader",
options: {
modules: true,
},
},
],
}),
},
How can I use absolute paths in my app?
A better way to import images in react app is using file loader in webpack and then directly importing images in application like you import other modules. First add file-loader in webpack like this
{
test: /\.(jpg|png)$/,
loader: "file-loader",
},
and then the public path of your server in webpack
output: {
path: __dirname + "/src/",
publicPath: "http://localhost:3000/static", // Your server public path
filename: "client.min.js"
},
Then in directly import image and put in src like this
import avatar from "../images/avatar.jpg";
<img src={avatar} />

Webpack Sass - cannot resolve images

I am trying to compile my Sass via webpack. Compiling normal sass is fine but I get an error.
Module not found: Error: Can't resolve '../img/twitter.svg' in '/Users/Steve/mywebsite/scss'
# ./~/css-loader!./~/sass-loader/lib/loader.js!./scss/main.scss 6:94501-94530
Is there a way to resolve this? Alternatively is there a way to set the level of the sass compiler to be less strict to just ignore certain errors
Below is my current config.
const path = require("path");
const ExtractTextPlugin = require("extract-text-webpack-plugin");
module.exports = {
resolve: {
alias: {
masonry: "masonry-layout",
isotope: "isotope-layout",
},
},
entry: "./main.js",
output: {
path: path.resolve(__dirname, "./dist/dist2"),
filename: "bundle.js",
},
module: {
rules: [
{
test: /\.(png|jpg|svg)$/,
include: path.join(__dirname, "/dist/img"),
loader: "url-loader?limit=30000&name=images/[name].[ext]",
},
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader?presets[]=es2015",
},
{
test: /\.scss$/,
use: ExtractTextPlugin.extract({
use: ["css-loader", "sass-loader"],
}),
},
{
test: /\.vue$/,
loader: "vue-loader",
options: {
loaders: {},
// other vue-loader options go here
},
},
],
},
plugins: [
// new webpack.optimize.UglifyJsPlugin(),
new ExtractTextPlugin("ross.css"),
],
};
I know this is late, but for anyone looking for a workaround this error;
In my case the image was loading perfectly in the template, however, Webpack was returning an error: Module not found: Error: Can't resolve './path/to/assets.png'
Fix/Workaround:
Add ?url=false to your css-loader, that will disable url handling by the css-loader :
...
{
loader: "css-loader?url=false"
},
...
I didn't have any luck with url-loader and file-loaderas suggested in the other answer. I was able to solve it using resolve-url-loader
module: {
rules: [
{ // sass / scss loader for webpack
test: /\.(sass|scss|svg|png|jpe?g)$/, //Make sure to allow all necessary file types here
use: ExtractTextPlugin.extract({
use: [
{
loader: 'css-loader',
options: {
importLoaders: 1,
minimize: true,
sourceMap: true
}
},
{
loader: 'postcss-loader',
options: {
sourceMap: true
}
},
{
loader: "resolve-url-loader", //resolve-url-loader needs to come *BEFORE* sass-loader
options: {
sourceMap: true
}
},
{
loader: "sass-loader",
options: {
sourceMap: true
}
}
]
})
}
],
},
This is a breaking change in css-loader 4.x (according to css-loader issue 1136).
You have not specified any loaders for images in your webpack file.
Install url-loader and file-loader to your package.json
via
npm install --save url-loader file-loader
Inside your webpack config file add following -
{
test : /\.(png|jpg|svg)$/,
include : path.join(__dirname, 'img'),
loader : 'url-loader?limit=30000&name=images/[name].[ext]'
}, // inline base64 URLs for <=30k images, direct URLs for the rest
I use this "Disable url resolving using the /* webpackIgnore: true */ comment"
https://webpack.js.org/loaders/css-loader/#disable-url-resolving-using-the--webpackignore-true--comment

Webpack: Loading images from html templates

I'm trying to set up an angular project using Webpack but I can't figure out how to reference images from within html templates and have them included in the build.
My project tree is as follows:
package.json
app/
- images/
- foo.png
- scripts/
- styles/
- templates/
I'm trying to use html-loader along with url-loader and file-loader but it's just not happening.
This is an example template: app/templates/foo.html
<img src="../images/foo.png" />
Problem #1: I would like to be able to reference images relative to app/. Right now, the paths need to be relative to the template file and this will get ugly very quickly (../../../images/foo.png).
Problem #2: Even if I specify the relative path, as I have done above, the project builds successfully but nothing really happens. The paths are left as-is and no images appear in dist/.
Here is my webpack config:
var path = require('path');
var webpack = require('webpack');
var ngminPlugin = require('ngmin-webpack-plugin');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var ngAnnotatePlugin = require('ng-annotate-webpack-plugin');
module.exports = function(config, env) {
var appRoot = path.join(__dirname, 'app/')
if(!env) env = 'development';
var webpackConfig = {
cache: true,
debug: true,
contentBase: appRoot,
entry: {
app: path.join(appRoot, '/scripts/app.coffee')
},
output: {
path: path.join(__dirname, 'dist/),
publicPath: '/',
libraryTarget: 'var',
filename: 'scripts/[name].[hash].js',
chunkFilename: '[name].[chunkhash].js'
},
module: {
loaders: [
{
test: /\.css$/,
loader: ExtractTextPlugin.extract("style-loader", "css-loader")
},
{
test: /\.scss$/,
loader: ExtractTextPlugin.extract('style-loader', 'css-loader!sass-loader?outputStyle=expanded&includePaths[]=./node_modules/foundation/scss/')
},
{
test: /\.coffee$/,
loader: 'coffee-loader'
},
{
loader: 'ngtemplate?relativeTo=' + (path.resolve(__dirname, './app')) + '/!html'
},
{
test: /\.png$/, loader: "url-loader?limit=100000&mimetype=image/png&name=[path][name].[hash].[ext]"
},
{
test: /\.jpg$/, loader: "file-loader?name=[path][name].[hash].[ext]"
},
{
test: /\.(woff|woff2)(\?(.*))?$/,
loader: 'url?prefix=factorynts/&limit=5000&mimetype=application/font-woff'
},
{
test: /\.ttf(\?(.*))?$/,
loader: 'file?prefix=fonts/'
},
{
test: /\.eot(\?(.*))?$/,
loader: 'file?prefix=fonts/'
},
{
test: /\.svg(\?(.*))?$/,
loader: 'file?prefix=fonts/'
},
{
test: /\.json$/,
loader: 'json'
}
]
},
resolve: {
extensions: [
'',
'.js',
'.coffee',
'.scss',
'.css'
],
root: [appRoot],
},
singleRun: true,
plugins: [
new webpack.ContextReplacementPlugin(/.*$/, /a^/),
new webpack.ProvidePlugin({
'_': 'lodash'
}),
new ExtractTextPlugin("styles/[name].[chunkhash].css", {allChunks: true}),
new HtmlWebpackPlugin({
template: appRoot + '/app.html',
filename: 'app.html',
inject: 'body',
chunks: ['app']
})
],
devtool: 'eval'
}
if(env === 'production') {
webpackConfig.plugins = webpackConfig.plugins.concat(
new ngAnnotatePlugin(),
new webpack.optimize.UglifyJsPlugin(),
new webpack.DefinePlugin({
'process-env': {
'NODE_ENV': JSON.stringify('production')
}
}),
new webpack.optimize.DedupePlugin(),
new webpack.optimize.UglifyJsPlugin()
);
webpackConfig.devtool = false;
webpackConfig.debug = false;
}
return webpackConfig;
}
If you are using HTML templates in Webpack 2, in addition to use the file-loader you need to change in your HTML:
<img src="../images/foo.png" />
to this
<img src=<%=require("../images/foo.png")%> />
Yes, you will have to do so for loading images from different path.
I had similar issue and I resolved this using file loader:
.
loaders: [{
// JS LOADER
test: /\.js$/,
loader: 'babel-loader?optional[]=runtime',
exclude: /node_modules/
}, {
// ASSET LOADER
test: /\.(woff|woff2|ttf|eot)$/,
loader: 'file-loader'
},
{
//IMAGE LOADER
test: /\.(jpe?g|png|gif|svg)$/i,
loader:'file-loader'
},
{
// HTML LOADER
test: /\.html$/,
loader: 'html-loader'
},
{
//SCSS LOADER
test: /\.scss$/,
loaders: ["style-loader", "css-loader", "sass-loader?indentedSyntax"]
}
]
Good Luck
For Webpack 5 you have to write this way:
module: {
rules: [
// other stuff above.....
{
test: /\.html$/,
use: [
{
loader: 'html-loader'
}
]
}
]
}
With Webpack 4, I was able to solve this problem by updating by html-loader to specify the root for my files. So given #syko's original structure; in webpack.config.js...
module: {
rules: [
// other stuff above.....
{
test: /\.html$/,
use: [
// ...The other file-loader and extract-loader go here.
{
loader: 'html-loader'
options: {
// THIS will resolve relative URLs to reference from the app/ directory
root: path.resolve(__dirname, 'app')
}
}
]
}
]
}
This tells the html-loader to interpret all absolute urls from the /app folder. So in our app/templates/foo.html, you can then use the following...
<img src="/images/foo.png" />
This then tells html-loader to see the above as path.resolve(__dirname, 'app', 'images', 'foo.png'). Then if you have extract-loader and/or file-loader, all the paths should be correct.
Managed to get this solution after hammering away at it for a while. The biggest confusion is where about in the loader stack the /images/foo.png is interpreted, in this case it starts at the html-loader plugin. Everything else after that, is more about how the image files are to be published.
Hope that helps.
You can use file-loader to extract images. Then using html-loader you can specify which tag-attribute combination should be processed by this loader via the query parameter attrs.
I could make it work with this configuration:
{
test: /\.(jpe?g|png|gif|svg|ico)$/i,
use: [{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'images/'
}
}]
},
{
test: /\.(html)$/,
use: {
loader: 'html-loader',
options: {
attrs: ['img:src', 'link:href']
}
}
}
Or in angular something like this:
attrs: [':ng-src', ':ng-href']

Categories

Resources