Webpack sass loader with sourcemaps and url statements - javascript

I have read that in order to have source maps, I have to use absolute urls in the url('') statement.
I did it this way :
body
background-image: url('/elements/assets/tmp_background.jpg')
It works when I remove the sourceMap option from the css loader, it does not if I activate it.
I think I might have failed somewhere on the absolute path point, do you have any ideas?
Here is my config file :
module.exports = {
devtool: 'source-map',
entry: [
'webpack/hot/dev-server',
'webpack-dev-server/client?http://localhost:8080',
path.resolve(__dirname, 'elements/main.js'),
],
output: {
path: 'dist',
publicPath: '/', // Prefix for all the statics urls
filename: 'bundle.js',
},
resolve: {
root: path.resolve(__dirname),
},
module: {
loaders: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader?presets[]=es2015',
},
{ test: /\.css$/, loaders: ['style', 'css'] },
{ test: /\.scss$/, loaders: ['style', 'css?sourceMap', 'sass?sourceMap'] },
{ test: /\.sass$/, loaders: ['style', 'css?sourceMap', 'sass?sourceMap&indentedSyntax=true'] },
{ test: /\.jade$/, loaders: ['ngtemplate', 'html', 'jade-html'] },
{ test: /\.(png|gif|jp(e)?g)$/, loader: 'url-loader?limit=8192' },
{ test: /\.(ttf|eot|svg|woff(2))(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: 'url-loader?limit=50000' },
],
},
};
On a more general idea, I could not find a working example of what I'm trying to do. I would be very interested if you can redirect me to that.

The publicPath can be used to fix this, until a cleaner solution appears.
See https://github.com/webpack/css-loader/issues/29

Related

Unexpected token given when loading import() with Webpack 4.24.0 or higher

I've been on a dependencies upgrade mission and I have found when upgrading Webpack to 4.24.0 or above I get this failure:
ERROR in ./src/js/components/App.jsx 35:9
Module parse failed: Unexpected token (35:9)
You may need an appropriate loader to handle this file type.
| import ReactModal from 'react-modal';
| var RoomListings = React.lazy(function () {
> return import('./RoomListings.jsx');
| });
| var RoomDetails = React.lazy(function () {
# ./src/js/index.js 3:0-39 6:74-77
# multi ./src/js/index.js
It's failing on the import but what is frustrating is that nothing has changed in either my Webpack or Babel config which are below:
webpack.config.js
module.exports = {
entry: ["./src/js/index.js"],
output: {
path: PATHS.build,
filename: "js/[name].js"
},
devServer: {
contentBase: path.join(__dirname, 'src'),
publicPath: '/'
},
module: {
rules: [
{ test: /\.js$/, exclude: /node_modules/, loader: "babel-loader"},
{ test: /\.jsx$/, loader: 'babel-loader', exclude: /node_modules/ },
{ test: /\.html$/, loader: "html-loader" },
{ test: /\.css$/, use: ['style-loader', 'css-loader'] },
{ test: /\.scss$/, use: ['style-loader', 'css-loader', 'sass-loader'] },
{ test: /\.(png|jp(e*)g|svg)$/, use: [{
loader: 'url-loader',
options: {
limit: 8000, // Convert images < 8kb to base64 strings
name: 'images/[hash]-[name].[ext]'
}
}]}
]
},
plugins: [
new HtmlWebPackPlugin({
template: "./src/index.html",
filename: "./index.html"
})
]
};
.babelrc
{
"presets": ["#babel/env", "#babel/react"],
"plugins": ["add-react-displayname", "#babel/plugin-syntax-dynamic-import", "emotion"],
"env": {
"test": {
"plugins": ["dynamic-import-node"]
}
}
}
I am assuming something is either missing or misconfigured, but after hours of searching SO and Google, none of the existing answer appear to help.

Extract specific CSS files to a file with Webpack

What I'm trying to achieve is a Webpack configuration where CSS is handled by the final JS export, but, some specific files are exported to an external file (to optimize critical CSS loading).
So, the idea is: if the file name start with _critical-, put it in a file.
So, here is my webpack.config.js for the moment:
const path = require('path');
const ExtractTextPlugin = require("extract-text-webpack-plugin");
module.exports = {
entry: './src/entry.js',
output: {
path: path.join(__dirname, 'public'),
filename: 'bundle.js'
},
module: {
rules: [
{
loader: 'babel-loader',
test: /\.js$/,
exclude: /node_modules/
},
{
use: [
'style-loader',
'css-loader',
'sass-loader'
],
test: /\.s?css$/,
},
{
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: [
'css-loader',
'sass-loader'
]
}),
test: /\A_critical-.*\.s?css$/,
},
{
test: /\.(png|jp(e*)g|svg)$/,
use: [{
loader: 'url-loader',
options: {
limit: 10000,
name: 'images/[hash]-[name].[ext]'
}
}]
}
]
},
plugins: [
new ExtractTextPlugin("styles.css"),
],
devtool: 'cheap-module-eval-source-map',
devServer: {
contentBase: path.join(__dirname, 'public'),
historyApiFallback: true
}
};
And, at some point, I have import './components/base/_critical-color.scss'; in my code.
When I run Webpack, no error. But no styles.css either.
What am I missing?

Webpack does not create output file (not using webpack-dev-server)

I am using webpack (NOT the dev-server, I know that doesn't output a file), and it is not creating a dist folder or output file.
I've tried running it directly through webpack (installed globally) and npm run build which uses a locally installed webpack. Neither work.
Here's my config:
const path = require('path');
module.exports = {
entry: {
app: './src/entry.js',
},
output: {
path: path.join('/dist'),
filename: '[name].bundle.js',
},
module: {
loaders: [
{
test: /\.tsx?$/,
loader: 'ts-loader',
},
{
test: /\.js$/,
exclude: /node_modules/,
loaders: ['ng-annotate'],
},
{
test: /\.js$/,
exclude: /(node_modules)/,
loader: 'babel', // 'babel-loader' is also a legal name to reference
query: {
presets: ['es2015', 'latest'],
},
},
{
test: /\.css$/,
loader: 'style-loader!css-loader',
},
{
test: /\.html$/,
loader: 'html',
},
{
test: /\.less$/,
loader: 'style!css!less',
},
],
},
resolve: {
extensions: ['', '.webpack.js', '.web.js', '.ts', '.tsx', '.js'],
root: [
path.resolve('./src'),
path.resolve('./node_modules'),
],
alias: {
vendor: path.join('/node_modules'),
},
fallback: ['node_modules'],
},
};
I've attempted to fix the problem by creating the dist folder manually, but that doesn't work either, the file still is not created.
The weird thing is that it DID build the file before, but now it's stopped. I've not changed the output location or the entry file at any point.
Any suggestions?
Your webpack output path is absolute:
output: {
path: path.join('/dist'), <----
filename: '[name].bundle.js',
},
My guess is it's being generated in your root directory. /dist would mean from the root of your file system, not relative to your project directory.
It should be:
output: {
path: path.join('./dist'),
filename: '[name].bundle.js',
},

Webpack - Error: Cannot define 'query' and multiple loaders in loaders list

This error appeared after I added the react-hot loader in an array following this tutorial: https://thoughtbot.com/blog/setting-up-webpack-for-react-and-hot-module-replacement
I'm getting Error: Cannot define 'query' and multiple loaders in loaders list.
var WebpackDevServer = require("webpack-dev-server");
var webpack = require('webpack');
var path = require('path');
require("babel-polyfill");
var BUILD_DIR = path.resolve(__dirname, 'build');
var APP_DIR = path.resolve(__dirname, 'src');
module.exports = {
entry: [
'babel-polyfill',
'bootstrap-loader',
'webpack/hot/dev-server',
APP_DIR + '/import.js',
],
output: {
path: BUILD_DIR,
filename: 'bundle.js'
},
module: {
loaders: [{
test: /\.jsx?$/,
loaders: ['react-hot', 'babel'],
exclude: /node_modules/,
query: {
plugins: ['transform-runtime'],
presets: ['es2015', 'stage-0', 'react']
}
}, {
test: /\.css$/,
loader: "style-loader!css-loader"
}, {
test: /\.scss$/,
loaders: ["style", "css", "sass"]
}, {
test: /\.(png|woff|woff2|eot|ttf|svg|jpg|gif)$/,
loader: 'url-loader?limit=100000'
}]
},
plugins: [
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery"
}),
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin()
]
};
It seems that the query is an alternative way of customizing the behaviour of a single loader, that is cleaner than specifying those parameters inline (see below). If multiple loaders are present, Webpack does not know to which the query configuration applies.
The following should solve your problem:
module: {
loaders: [{
test: /\.jsx?$/,
exclude: /node_modules/,
loaders: ['react-hot', 'babel?presets[]=es2015,presets[]=stage-0,presets[]=react,plugins[]=transform-runtime']
}
EDIT: While this solution works for Webpack 1, see the other answers for cleaner solutions that work in more recent versions.
My Solution:
loaders: [{
test: /\.(js|jsx)$/,
loaders: ['react-hot', 'babel?' + JSON.stringify({
cacheDirectory: true,
plugins: [
'transform-runtime',
'transform-decorators-legacy'
],
presets: ['es2015', 'react', 'stage-0'],
env: {
production: {
presets: ['react-optimize']
}
}
}), 'eslint'],
include: src,
exclude: /node_modules/
}
In webpack 2 & 3 this can be configured much more cleanly.
Loaders can be passed in an array of loader objects. Each loader object can specify an options object that acts like the webpack 1 query for that particular loader.
For example, using both react-hot-loader and babel-loader, with babel-loader configured with some options, in webpack 2/3
module: {
rules: [{
test: /\.js$/,
exclude: /node_modules/,
use: [{
loader: 'react-hot-loader'
}, {
loader: 'babel-loader',
options: {
babelrc: false,
presets: [
'es2015-native-modules'
'stage-0',
'react'
]
}
}]
}]
}
For comparison, here is the same configuration in webpack 1, using the query string method.
module: {
rules: [{
test: /\.js$/,
exclude: /node_modules/,
loaders: [
'react-hot',
'babel-loader?' +
'babelrc=false,' +
'presets[]=es2015,' +
'presets[]=stage-0,' +
'presets[]=react'
]
}]
}
Notice the changed property names all down the chain.
Also, note that I changed the es2015 preset to es2015-native-modules preset in the babel-loader configuration. This has nothing to do with the specification of options, it's just that including es6 modules allows you to use webpack tree-shaking feature introduced in v2. It could be left alone and it would still work, but the answer would feel incomplete without that obvious upgrade being pointed out :-)
Disclaimer: This is the same as my answer to a similar question, but this question has similar votes/views/google ranking, so I'll post the answer here too.
For webpack 2. I manage to configure like this:
var webpack = require("webpack");
var path = require("path");
module.exports = {
entry: "./src/index.js",
output: {
path: path.resolve(__dirname, "dist/assets"),
filename: "bundle.js",
publicPath: "/assets/"
},
devServer: {
inline: true,
contentBase: './dist',
port: 3000
},
module: {
loaders: [
{
test: /\.js$/,
exclude: /(node_modules)/,
loader: "babel-loader",
options: {
presets: ['latest', 'react', 'stage-0']
}
}
]
}
};
This solution worked for me:
module: {
loaders:[
{
test: /\.js$/,
exclude: /(node_modules)/,
loader: 'babel-loader'
}
]
}
and presets in the .babelrc
{
'presets': ['latest', 'react', 'stage-0']
}
please refer to https://webpack.github.io/docs/usage.html
I had faced the same issue since I found a solution for myself. you can try it:
--- here is the solution ---
If you've defined "presets" in ".babelrc" file
then you don't need to specify it in the "webpack.config.js" file, then delete it and it works well
and if you don't,
I recommend you to go to your ".babelrc" file and specify your presets there

Use webpack with jade-loader without explicitly requiring assets

I am trying to use Webpack jade-loader in combination with html-loader to be able to omit requires in jade templates + use a path relative to a certain folder. I have tried a few things, none of them worked.
By default jade-loader works when using img(src=require("../../../../assets/images/imac.png") alt="computer"), with the following webpack config:
module.exports = {
devtool: 'eval',
entry: [
'webpack-dev-server/client?http://localhost:3000',
'webpack/hot/only-dev-server',
'./app/app.js'
],
context: path.resolve(__dirname + "/client"),
output: {
path: path.join(__dirname, 'dist'),
filename: 'bundle.js',
publicPath: '/static/'
},
plugins: [
new webpack.HotModuleReplacementPlugin()
],
module: {
// placed here so we know that it is done before transpiling
preLoaders: [
{ test: /\.js$/, loader: "eslint-loader", exclude: [/node_modules/, /\.config\.js/, /\.conf\.js/ ] }
],
loaders: [
{ test: /\.html$/, loader: 'raw' },
{ test: /\.jade$/, loader: 'jade-loader' },
{ test: /\.less$/, loader: 'style!css!less' },
{ test: /\.css/, loader: 'style!css' },
{ test: /\.(png|jpg|jpeg|svg)$/, loader: 'file' },
{ test: /\.js$/, loader: 'babel?stage=1', exclude: [/client\/lib/, /node_modules/, /\.spec\.js/] }
]
},
eslint: {
configFile: './.eslintrc'
}
};
If I add the html-loader ({ test: /\.jade$/, loader: 'html-loader!jade-loader' }) which is supposed to require sources by default, I keep getting the 'Error: Module not found'. The console logs all the paths that it tried, all relative to the current working file.
I tried to give it some context, with context: path.resolve(__dirname + "/client"). It didn't work either.
I also tried to combine with the raw loader: raw-loader!html-loader!jade-loader. I don't get the error but the wepback output that is served is not my app at all, but instead something along the lines of:
var jade = require(/......) ....
Do you have any idea ?
Thanks for your help
Had the same Problem.
https://www.npmjs.com/package/pug-html-loader worked for me:
module.exports = {
// your config settings ...
module: [
//your modules...
loaders: [{
include: /\.jade/,
loader: 'pug-html-loader'
}]
]
};
I don't know what do you want. My need is to load a template from a directive (component in 1.5)
angular.module('app').component('myComponent', {
bindings: {},
template: require('./mytemplate.jade')()
});
You can to note that I'm invoking the returned function.

Categories