webpack - require('node_modules/leaflet/leaflet.css') - css

So I'm trying to build a map app using webpack and leaflet. I can require leaflet.js from my map.js file, but I can't call leaflet.css without getting an error.
My current webpack.config.js looks like:
'use strict'
var webpack = require('webpack'),
path = require('path'),
HtmlWebpackPlugin = require('html-webpack-plugin'),
srcPath = path.join(__dirname, 'src');
module.exports = {
target: "web",
cache: true,
entry: {
app: path.join(srcPath, "index.js")
},
resolve: {
alais: {
leaflet_css: __dirname + "/node_modules/leaflet/dist/leaflet.css"
}
},
module: {
loaders: [
{test: /\.js?$/, exclude: /node_modules/, loader: "babel-loader"},
{test: /\.scss?$/, exclude: /node_modules/, loader: "style!css!sass!"},
{test: /\.css?$/, loader: "style!css!"}
]
},
plugins: [
new webpack.optimize.CommonsChunkPlugin("common", "common.js"),
new HtmlWebpackPlugin({
inject: true,
template: "src/index.html"
}),
new webpack.NoErrorsPlugin()
],
output: {
path: path.join(__dirname, "dist"),
publicPath: "/dist/",
filename: "[name].js",
pathInfo: true
}
}
And my main.js file looks like:
var $ = require('jquery'),
leaflet = require('leaflet');
require("./sass/main.scss");
require("leaflet_css");
var map = L.map('map').setView([51.505, -0.09], 13);
L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors'
}).addTo(map);
L.marker([51.5, -0.09]).addTo(map)
.bindPopup('A pretty CSS3 popup.<br> Easily customizable.')
.openPopup();
console.log('I got called');
What is the correct approach of bundling css files from 3rd party suppliers via webpack?
I saw this project were leaflet is stored in the libs directory... what's the reason for this, why store it in the libs directory if it is installed into the node_modules direcory via npm?
This is very much a learning exercise so any pointers are greatly appreciated! :)

So it turns out, the answer is a combination of webpack's resolve.alias and the file loader. My new webpack file looks like this:
'use strict'
var webpack = require('webpack'),
path = require('path'),
HtmlWebpackPlugin = require('html-webpack-plugin'),
srcPath = path.join(__dirname, 'src');
module.exports = {
target: "web",
cache: true,
entry: {
app: path.join(srcPath, "index.js")
},
resolve: {
extensions: ['', '.html', '.js', '.json', '.scss', '.css'],
alias: {
leaflet_css: __dirname + "/node_modules/leaflet/dist/leaflet.css",
leaflet_marker: __dirname + "/node_modules/leaflet/dist/images/marker-icon.png",
leaflet_marker_2x: __dirname + "/node_modules/leaflet/dist/images/marker-icon-2x.png",
leaflet_marker_shadow: __dirname + "/node_modules/leaflet/dist/images/marker-shadow.png"
}
},
module: {
loaders: [
{test: /\.js?$/, exclude: /node_modules/, loader: "babel-loader"},
{test: /\.scss?$/, exclude: /node_modules/, loader: "style-loader!css-loader!sass-loader!"},
{test: /\.css?$/, loader: "style-loader!css-loader!"},
{test: /\.(png|jpg)$/, loader: "file-loader?name=images/[name].[ext]"}
]
},
plugins: [
new webpack.optimize.CommonsChunkPlugin("common", "common.js"),
new HtmlWebpackPlugin({
inject: true,
template: "src/index.html"
}),
new webpack.NoErrorsPlugin()
],
output: {
path: path.join(__dirname, "dist"),
publicPath: "/dist/",
filename: "[name].js",
pathInfo: true
}
}
And then all I need to do is require the icons in the .js file
require("./sass/main");
require("leaflet_css");
require("leaflet_marker");
require("leaflet_marker_2x");
require("leaflet_marker_shadow");
Lovely!!! :)

I managed to do it easier. Just needed to add loaders for css and for png
loaders: [
{ test: /\.css$/, loader: 'style-loader!css-loader' },
{
test: /\.png$/,
loader: 'url-loader',
query: { mimetype: 'image/png' }
}
]

Related

Unable to inline styles with `sass-loader`

I have a project setup where I use ExtractTextPlugin to create a CSS file. I'm trying to create a dev Webpack config with the styles injected onto the page using style-loader, css-loader, and sass-loader.
As far as I am aware the default behaviour is to inject the styles into a <style /> tag and I've removed all traces of ExtractTextPlugin but it still doesn't want to inject the styles.
Does anybody know what might cause the styles to be lost? My Webpack config is below.
Config:
const webpack = require('webpack')
module.exports = config => Object.assign({}, {
module: {
loaders: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader'
},
{
test: /\.scss$/,
use: [
'style-loader',
'css-loader',
'sass-loader'
]
}
]
},
plugins: [
new webpack.SourceMapDevToolPlugin({
filename: 'bundle.js.map'
}),
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('development')
})
]
}, config)
Called with:
module.exports = require('../../dev')({
name: 'Onboarding',
entry: './src/apps/components/Onboarding/index.js'
})
I was able to get it working by rewriting most of my Webpack config. I had already tried the css-loader options below, so I'm not sure why they worked now but not before.
This is my new dev-only config:
const webpack = require('webpack')
const path = require('path')
const HTMLWebpackPlugin = require('html-webpack-plugin')
module.exports = config => {
const { out, libraryTarget, name = 'main' } = config
const filename = `${name}.js`
delete config.out
return Object.assign({}, {
output: {
path: path.resolve(__dirname, '../../../' + out),
filename,
libraryTarget,
publicPath: '/assets/js/'
},
devtool: 'source-map',
module: {
loaders: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader'
},
{
test: /\.scss$/,
use: [
'style-loader',
{
loader: 'css-loader',
query: {
importLoaders: 1,
modules: true,
localIdentName: '[name]_[local]_[hash:base64:5]'
}
},
'sass-loader']
}
]
},
plugins: [
new HTMLWebpackPlugin({
title: 'App Name',
filename: '../../index.html',
template: './test-lambda/template-dev.html',
inject: 'body'
}),
new webpack.HotModuleReplacementPlugin(),
new webpack.SourceMapDevToolPlugin({
filename: `${filename}.map`
}),
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('development')
})
]
}, config)
}

Less module build failed in webpack after migrating from grunt

I can't figure out how to compile my less files to css and then include them in my build folder, without the app failing to run. Trying to build/run the application returns the following error:
ERROR in ./content/styles/less/ts.less
Module build failed:
#import "node_modules/bootstrap/less/mixins/buttons.less";
#import "node_modules/Font-awesome/less/font-awesome.less";
^
Can't resolve './node_modules/Font-awesome/less/font-awesome.less' in '/home/thinkpad/work/EPD.SPA/EpdSPA/content/styles/less'
in /home/thinkpad/work/EPD.SPA/EpdSPA/content/styles/less/ts.less (line 4, column 0)
# multi ./content/styles/less/for.less ./content/styles/less/kladd.less ./content/styles/less/ts.less
To clarify: These files have already proved to be working with grunt. The webpack migration triggered these errors.
I'm using the webpack config examples from here. My config file:
var webpack = require('webpack');
var globby = require('globby');
var path = require('path');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var CleanWebpackPlugin = require('clean-webpack-plugin');
var AssetsPlugin = require('assets-webpack-plugin');
var CopyWebpackPlugin = require('copy-webpack-plugin');
const extractLESS = new ExtractTextPlugin('stylesheets/[name]-two.css');
module.exports = {
entry: {
app: globby.sync(['./app/app.js','./app/app.run.js', './app/app.config.js', './app/**/*.js']),
styles: globby.sync(['./content/styles/*.css']),
lessStyles: globby.sync(['./content/styles/less/*.less']),
images: globby.sync(['./content/images/**/*.*']),
vendor: [
// removed to save space
]
},
output: {
filename: './scripts/[name].bundle.js',
path: path.join(__dirname, "public")
},
devServer: {
port: 1384,
contentBase: './public/'
},
// Enable sourcemaps for debugging webpack's output.
devtool: 'source-map',
module: {
rules: [
{ test: /\.less$/,
use: extractLESS.extract([ 'css-loader', 'less-loader' ])
},
{
test: /\.html$/,
loader: 'raw-loader',
exclude: [/node_modules/]
},
{
test: /\.css$/,
loader: ExtractTextPlugin.extract({ fallback: 'style-loader', use: 'css-loader' }),
},
{
test: /\.(ico)$/,
loader: "url-loader?name=./[name].[ext]",
include: path.resolve(__dirname, "content", "images")
},
{
test: /\.svg$/,
loader: 'svg-loader'
},
{
test: /\.(jpg|jpeg|gif|png|PNG|tiff|svg)$/,
loader: 'file-loader?name=/[path]/[name].[ext]',
include: path.resolve(__dirname, "content", "images"),
},
{
test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
loader: 'url-loader?minetype=application/font-woff&name=./fonts/[name].[ext]'
},
{
test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
loader: 'file-loader?name=./fonts/[name].[ext]'
},
{
test: require.resolve('adal-angular/lib/adal'),
loader: 'expose-loader?AuthenticationContext'
},
{
test: /\.js$/,
enforce: "pre",
loader: 'source-map-loader'
}
],
},
plugins: [
new HtmlWebpackPlugin({
template: './app/layout.html',
filename: 'index.html'
}),
new webpack.optimize.CommonsChunkPlugin({ name: 'vendor', filename: './scripts/vendor.bundle.js' }),
new ExtractTextPlugin({ filename: './[name].bundle.css' }),
/*
new CleanWebpackPlugin(['./public'], {
verbose: false
}),
*/
new AssetsPlugin({
filename: 'webpack.assets.json',
path: './public/scripts',
prettyPrint: true
}),
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
'window.jQuery': 'jquery',
'window.$': 'jquery',
"window.AuthenticationContext": "AuthenticationContext",
_: 'underscore'
}),
new CopyWebpackPlugin([
{from: './app/**/*.html', to: './'}
]),
extractLESS // including the less files here
],
externals: [
{ xmlhttprequest: '{XMLHttpRequest:XMLHttpRequest}' }
]
}
Here you can see that the less files have been compiled to css and included in the public(build) folder. Why do i get errors, if the config file executes as intended?
Here it also shows that all the files are included in the application in the browser as well. I have checked all my dependencies and they are all running latest versions.
The path for the imports in the less files, were incorrect. Here is the working references:
#import "~bootstrap/less/variables.less";
#import "~bootstrap/less/mixins/buttons.less";
#import "~font-awesome/less/font-awesome.less";
I think the problem is with your font_awesome path.
Try to change import to (font_awesome instead of Font_awesome)
#import "node_modules/font-awesome/less/font-awesome.less";

sass-loader with extract-text-plugin not outputting file

I have configured my webpack.config.js as following:
var debug = process.env.NODE_ENV !== "production";
var webpack = require('webpack');
var path = require('path');
// plugins
var ExtractTextPlugin = require('extract-text-webpack-plugin');
module.exports = {
context: path.join(__dirname, "src"),
devtool: debug ? "inline-sourcemap" : null,
entry: "./js/init.js",
module: {
loaders: [
{
test: /\.jsx?$/,
exclude: /(node_modules|bower_components)/,
loader: 'babel',
query: {
presets: ['react', 'es2015', 'stage-0'],
plugins: ['react-html-attrs', 'transform-decorators-legacy', 'transform-class-properties',],
}
},
{
test: /\.json$/,
include: /node_modules/,
loader: 'json-loader'
},
{
test: /\.scss$/,
loaders: ExtractTextPlugin.extract(
'style',
'css!sass'
)
}
]
},
output: {
path: __dirname + "/src/",
filename: "app.js"
},
plugins: debug ? [] : [
new webpack.optimize.DedupePlugin(),
new webpack.optimize.OccurenceOrderPlugin(),
new webpack.optimize.UglifyJsPlugin({ mangle: false, sourcemap: false }),
new ExtractTextPlugin('default.css'),
],
devServer: {
port: 3000,
historyApiFallback: {
index: 'index.html'
}
},
sassLoader: {
includePaths: [path.resolve(__dirname, "src/css/sass")]
},
resolve: {
alias: {
'#': path.resolve(__dirname, 'src/js'),
'!': path.resolve(__dirname, 'src/css/sass')
}
},
};
And this is my file structure:
- src
-- css
--- sass
---- default.scss
-- js
-- index.html
Yet I don't see my default.css file exported anywhere when I run webpack dev server. Does it not work with webpack dev server?
Edit: Simply running webpack does not work either.

Webpack: wrong absolute path in compiled CSS

I'm migrating an Angular 1 project in order to be able to deploy everything with Webpack.
So far, I managed to configure almost everything but I'm having issues trying to export the static assets (fonts and images mostly).
I've configured the ExtractTextPlugin as below
{ test: /\.css$/, loader: ExtractTextPlugin.extract('style-loader','css-loader', {allChunks: true}) }
and in the compiled CSS the paths are replaced but the resulting absolute path is wrong. In fact the resulting path is /assetsweb/assets/.. while I expect it to be /assets/...
I cannot understand where the /assetsweb part is coming from.
Here's the Webpack configuration I'm using
var webpack = require("webpack");
var path = require("path");
var ExtractTextPlugin = require("extract-text-webpack-plugin");
module.exports = {
context: __dirname + "/src",
entry:{
web: "./web/wayonara.js",
mobile: "./mobile/wayonara.js"
},
output:{
path: __dirname + "/dist",
filename: "/[name]/bundle.js",
publicPath: "/assets"
},
plugins:[
new webpack.DefinePlugin({
ENV: JSON.stringify('dev')
}),
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery",
"window.jQuery": "jquery",
EXIF: "exif-js",
"window.EXIF":"exif-js"
}),
new ExtractTextPlugin("/[name]/assets/css/bundle.css")
],
module:{
loaders: [
{
loader: "babel-loader",
test: /\.js?$/,
exclude: [/node_modules/, /bower_components/],
query: {
presets: ['es2015']
}
},
{ test: /\.html$/, loader: "html" },
{ test: /\.css$/, loader: ExtractTextPlugin.extract('style-loader','css-loader', {allChunks: true}) },
{
test: /\.(jpg|jpeg|png|svg)$/,
loader: "file-loader?name=[path][name].[ext]"
},
{
test: /\.(woff|woff2|ttf|eot|svg)(\?v=\d+\.\d+\.\d+)?/,
loader: 'file-loader?name=[path][name].[ext]'
}
]
}
};
Can you help me? Thanks in advance,
Best,
Maurizio

How to get svg from MDL working with webpack

Using a checkbox component form Material Design Lite, i.e.
https://getmdl.io/components/index.html#toggles-section/checkbox
the tickmark.svg is not shown properly when I use
import '../../node_modules/material-design-lite/src/material-design-lite.scss';
for bundling with npm and webpack. Instead of:
I get:
In the browser I find the following path to tickmark.svg which is the svg that is 'missing':
When using either one of these two alternatives it works as it should:
1) import '../../node_modules/material-design-lite/.tmp/material-design-lite.css';
2) import '../../node_modules/material-design-lite/material.min.css';
To compare, when using 2 I get following in the browser:
My webpack.config.js:
var path = require('path');
var webpack = require('webpack');
var BundleTracker = require('webpack-bundle-tracker');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var Clean = require('clean-webpack-plugin');
var bootstrapPath = path.join(__dirname, 'node_modules/bootstrap/dist/css');
var sourcePath = path.join(__dirname, 'assets');
module.exports = {
devtool: 'eval-source-map',
context: __dirname,
entry: [
'./assets/js/index' // entry point of our app. .assets/js/index.js should require other js modules and dependencies it needs
],
output: {
path: path.resolve('./assets/bundles/'),
filename: '[name]-[hash].js',
}
,
node: {
console: true,
fs: 'empty'
}
,
plugins: [
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery'
}),
new BundleTracker({filename: './webpack-stats.json'}),
new webpack.BannerPlugin('Pqbq Banner!!!! todo'),
new HtmlWebpackPlugin({
template: __dirname + '/assets/index.tmpl.html'
}),
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin(),
new Clean(['assets/bundles'])
],
module: {
preloaders: [
{
test: /\.js/,
loader: 'eslint'
}
],
loaders: [
{
test: /\.js[x]?$/,
loader: 'babel',
exclude: /(node_modules|bower-components)/,
query: {
presets: ['es2015', 'stage-0']
}
},
{
test: /\.json$/,
loader: 'json-loader'
},
{
test: /\.js$/,
include: path.resolve(__dirname, 'node_modules/mapbox-gl/js/render/shaders.js'),
loader: 'transform/cacheable?brfs'
},
{
test: /\.js$/,
include: path.resolve(__dirname, 'node_modules/webworkify/index.js'),
loader: 'worker'
},
// {
// test: /\.css$/,
// loader: 'style!css?modules!postcss'
// },
{
test: /\.scss$/,
loaders: ['style', 'css?sourceMap', 'sass?sourceMap']
},
// {test: /\.(woff2?|svg)$/, loader: 'url?limit=10000'},
// {test: /\.(ttf|eot)$/, loader: 'file'},
{test: /\.css$/, loader: 'style-loader!css-loader'},
{test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, loader: 'file'},
{test: /\.(woff|woff2)$/, loader: 'url?prefix=font/&limit=5000'},
{test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, loader: 'url?limit=10000&mimetype=application/octet-stream'},
// {test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, loader: 'url?limit=10000&mimetype=image/svg+xml'},
{test: /\.svg$/, loader: 'url?limit=8192!svgo'},
]
}
,
postcss: [
require('autoprefixer')
],
resolve: {
modulesDirectories: ['node_modules', 'bower_components', bootstrapPath, sourcePath],
extensions: ['', '.js', '.jsx', '.css'],
alias: {
webworkify: 'webworkify-webpack',
'$': 'jquery',
'jQuery': 'jquery'
}
}
,
devServer: {
contentBase: './assets',
colors: true,
historyApiFallback: true,
inline: true,
hot: true
}
};
To fix this I had to override the $image_path variable by creating my own material.scss file. I grabbed this file:
https://github.com/google/material-design-lite/blob/master/src/material-design-lite.scss
and then added:
#import "./variables";
at the top.
In that file I added this line:
$image_path: '~material-design-lite/dist/images/' !default;

Resources