How to configure Webpack to not pull content of imported Sass files to a source map? - node.js

I have a Sass file that imports Bootstrap and Font Awesome.
They has been put on the of the file before my custom CSS class.
Here is the code:
/src/scss/site.scss
#import "~bootstrap/scss/bootstrap";
#import "~font-awesome/scss/font-awesome";
// Custom style sheet here
.my-custom-header{
color:#F00
}
There is a source map after Webpack build but it includes the content of Bootstrap and font awesome.
Here what is look like in Browser:
When I tried to inspect a custom class it point to correct line number of origin source code but incorrect for generated source map because it has content of Bootstrap in the top.
My question is:
Is it possible to configure a output source map to keep the import statement and the content is exact the same as actual source code.
Here what source map I'm expected.
site.css.map
#import "~bootstrap/scss/bootstrap";
#import "~font-awesome/scss/font-awesome";
// Custom style sheet here
.my-custom-header{
color:#F00
}
Here my Webpack configuration:
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const siteFile = [__dirname, 'src', 'scss', 'site'];
const outputPath = [__dirname, 'public', 'css'];
module.exports = {
entry: {
site: path.resolve(...siteFile),
},
output: {
path: path.resolve(...outputPath),
},
resolve: {
// https://github.com/webpack/webpack-dev-server/issues/720#issuecomment-268470989
extensions: ['.scss']
},
devtool: 'source-map',
module: {
rules: [
{
test: /\.scss$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
},
{
loader: 'css-loader', // Translates CSS into CommonJS modules
options: {
sourceMap: true
}
},
{
loader: 'postcss-loader', // Run post css actions
options: {
plugins: () => {
// post css plugins, can be exported to postcss.config.js
return [
require('precss'),
require('autoprefixer')
];
},
sourceMap: true
}
},
{
loader: 'resolve-url-loader',
},
{
loader: 'sass-loader', // Compiles Sass to CSS, using node-sass by default
options: {
sourceMap: true
}
}
],
exclude: /node_modules/
},
{
test: /\.(png|jpe?g|gif|svg|eot|ttf|woff2?)$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: '.' //relative to output
}
}
]
}
]
},
plugins: [
new MiniCssExtractPlugin({
filename: './[name].css' // relative to output
}),
],
devServer: {
contentBase: path.join(__dirname, 'public'),
compress: false,
port: 8080,
}
};
Here is a link to a repository of the example code.
codesanook-examples-webpack
Thank you.

Have you tried SourceMapDevToolPlugin?
https://webpack.js.org/plugins/source-map-dev-tool-plugin/
You might need to create a vendor bundle for node modules stuff then you can ignore it from sourcemap.

Related

webpack relative url in css, creating copied export svg files

I have the below webpack.config. I'm trying to use relative url in my style.css to point to some svg files. The problem is the relative url is referencing a copy of the svg file which is just an export statement. Does anyone know why my webpack.config is creating these copied svg files? The files aren't working to show the image but the original svg does, so just trying to get webpack to stop creating the copied export file and just reference the actual svg. Thanks.
webpack.config.cs:
const path = require('path');
const webpack = require('webpack');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const { VueLoaderPlugin } = require("vue-loader");
const srcPath = path.resolve(__dirname, './src');
const stylePath = path.resolve(srcPath, './styles');
const bldPath = path.resolve('../SpeedRunApp/wwwroot/dist');
module.exports = {
devtool: 'source-map',
entry: {
master: path.resolve(srcPath, 'index.js'),
style: `${stylePath}/style.css`
},
mode: 'development',
watch: true,
module: {
rules: [
{
test: /\.scss$/,
use: [{ loader: 'style-loader' },
{ loader: 'css-loader' },
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [ require('autoprefixer') ]
}
}
},
{ loader: 'sass-loader' }]
},
{
exclude: /(node_modules|bower_components)/,
include: srcPath,
test: /\.js$/,
use: [{ loader: 'babel-loader' }]
},
{
test: /\.(woff(2)?|ttf|eot|svg)(\?v=\d+\.\d+\.\d+)?$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
publicPath: './fonts/',
outputPath: './fonts/',
esModule: false
}
}
]
},
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, 'css-loader']
},
{
test: /\.vue$/,
loader: 'vue-loader'
},
{
test: /\.(png|jpg|jpeg|gif)$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: './images/',
publicPath: './images/',
esModule: false
}
}
]
}
]
},
optimization: {
splitChunks: {
cacheGroups: {
vendors: {
chunks: 'all',
name: 'vendor',
test: /[\\/]node_modules[\\/]/
}
}
},
},
output: {
filename: '[name].min.js',
chunkFilename: '[name].min.js',
globalObject: 'this',
path: `${bldPath}`,
publicPath: '/dist/'
},
plugins: [
new CleanWebpackPlugin({
cleanOnceBeforeBuildPatterns: [`${bldPath}/**`],
dry: false,
verbose: true,
dangerouslyAllowCleanPatternsOutsideProject: true
}),
new VueLoaderPlugin(),
new MiniCssExtractPlugin({
filename: '[name].min.css'
})
]
};
style.css:
.twitter-logo {
background: url(../fonts/Twitter_Logo_WhiteOnBlue.svg)
}
.twitch-logo {
background: url(../fonts/TwitchGlitchPurple.svg)
}
.youtube-logo {
background: url(../fonts/youtube_social_square_red.svg)
}
Weird copy files webpack is creating:
Content of copied files:
I bailed on using the css and just went with importing the svgs, changed code to this and works. I put my own non-fontawesome svgs in the "font" folder in the Node.js project (webpack project) and that is correctly copying them to the static font folder in the Web MCV project.
Index.js
import '#fortawesome/fontawesome-free/js/all.min.js'
import './fonts/TwitchGlitchPurple.svg';
import './fonts/Twitter_Logo_WhiteOnBlue.svg';
import './fonts/youtube_social_square_red.svg';
import './fonts/pie-chart.svg';
Node.js (webpack) project:
Successful copy to static folder in Web.MVC project:
Code using svg:

Critical dependency: require function is used in a way in which dependencies cannot be statically extracted - NodeJS, Express & Webpack

I am developing a web application using Node.js, Express & Webpack. Everything was going well until Webpack was upgraded to Webpack 5 and lots of bugs appeared. I have managed to solve all the errors but there is a warning I can't solve. I have seen this post but it's related to Angular so I don't think it helps me much: Critical dependency: require function is used in a way in which dependencies cannot be statically extracted
WARNING in ./node_modules/terser-webpack-plugin/dist/minify.js
Critical dependency: require function is used in a way in which dependencies cannot be statically extracted
This is my webpack.config.js; resolve fields and node-polyfill-webpack-plugin are used to solve Webpack 5 bugs and errors.
const path = require("path")
const NodePolyfillPlugin = require("node-polyfill-webpack-plugin")
const webpack = require('webpack')
const HtmlWebPackPlugin = require("html-webpack-plugin")
module.exports = {
resolve:{
fallback: {
"fs": false,
"path": false,
"worker_threads":false,
"child_process":false,
"http": false,
"https": false,
"stream": false,
"crypto": false,
}
},
entry: {
main: './src/js/main.js',
index:'./src/js/'
},
output: {
path: path.join(__dirname, 'dist'),
//publicPath: '/',
filename: '[name].js'
},
mode:"development",
target: 'web',
devtool: 'source-map',
module: {
rules: [
{
test: /\.(png|jp(e*)g|svg)$/,
use: [{
loader: 'url-loader',
options: {
limit: 8000, // Convert images < 8kb to base64 strings
name: 'images/[hash]-[name].[ext]'
}
}]
},
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader",
},
{
test: /\.bpmn$/,
use: 'raw-loader'
},
{
// Loads the javacript into html template provided.
// Entry point is set below in HtmlWebPackPlugin in Plugins
test: /\.html$/,
use: [
{
loader: "html-loader",
//options: { minimize: true }
}
]
},
{
test: /\.css$/,
use: [ 'style-loader', 'css-loader' ]
}
]
},
plugins: [
new HtmlWebPackPlugin({
template: '!!raw-loader!./src/views/pages/index.ejs',
filename: "./index.ejs",
excludeChunks: [ 'server', 'main' ]
}),
new HtmlWebPackPlugin({
template: '!!raw-loader!./src/views/pages/bmv.ejs',
filename: "./bmv.ejs",
excludeChunks: [ 'server', 'index' ]
}),
new webpack.NoEmitOnErrorsPlugin(),
new NodePolyfillPlugin()
]
}
configure the webpack:
const path = require('path');
module.exports = {
//...
resolve: {
alias: {
'terser-webpack-plugin': path.resolve(__dirname, 'node_modules/terser-webpack-plugin/dist/minify.js'),
},
},
};

Migrating RequireJS/AMD with Plugins to Webpack

I'm working on migrating a large RequireJS application to Webpack. The basic build with Webpack seems to work fine -- I've moved "paths" definitions to "alias" and I've setup loaders for my content and shims, like jQuery.
However, there's a remaining issue I'm not sure how to resolve. Basically the RequireJS app uses the "text-plugin" to include HTML templates, and Webpack is throwing "Module not found" errors for the HTML templates.
An example AMD module I want to bundle looks something like this:
AMD Module with Text Plugin
define([
'security',
'modals',
'text!../templates/contact_info.html'
], function(security, modals, contactInfoTemplate) {
return {
foo: function() { return "bar"; }
};
});
I thought I could use the raw-loader to load the template files. I aliased 'text' to be the 'raw-loader':
text: {
test: /\.html$/,
loader: "raw-loader"
},
However, I'm seeing the following error for all of my templates that are required like above:
Module not found: Error: Can't resolve 'text'
BREAKING CHANGE: It's no longer allowed to omit the '-loader' suffix when using loaders. You need to specify 'text-loader' instead of 'text'.
I tried replacing 'text!...' with 'text-loader!...', and I then see this error complaining that it can't load/find the HTML module!
Module not found: Error: Can't resolve '../templates/contact_info.html'
webpack.config.js, version 3.9.1
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const path = require('path');
const webpack = require('webpack');
let basePath = path.join(__dirname, '/');
module.exports = {
entry: {
'main': basePath + 'js/main.js',
},
context: __dirname,
output: {
path: __dirname + '/build',
filename: '[name].min.js',
libraryTarget: 'amd',
umdNamedDefine: true
},
module: {
rules: [
{
test: /(\.js)$/,
exclude: /(node_modules)/,
use: {
// babel-loader to convert ES6 code to ES5 + amdCleaning requirejs code into simple JS code, taking care of modules to load as desired
loader: 'babel-loader',
options: {
presets: ['#babel/preset-env'],
plugins: []
}
}
},
{
test: /\.css$/,
use: [
{ loader: "style-loader" },
{ loader: "css-loader" }
]
},
{ test: /\.jpg$/, use: [ "file-loader" ] },
{ test: /\.png$/, use: [ "url-loader?mimetype=image/png" ] },
{
test: /\.(html)$/,
use: {
loader: 'raw-loader',
options: {
minimize: true
}
}
}
]
},
resolve: {
modules: [
'js/**/*.js',
'node_modules',
path.resolve('./js')
],
extensions: ['.js'], // File types,
alias: {
text: {
test: /\.html$/,
loader: "raw-loader"
},
bridge: 'libs/bridge',
cache: 'libs/cache',
cards: 'libs/cards',
moment: 'libs/moment',
underscore: 'libs/underscore',
}
},
plugins: [
new CleanWebpackPlugin(['dist']),
new HtmlWebpackPlugin({
filename: 'index.html',
template: '../index.html'
}),
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery'
})
]
};
Anyone know how to get Webpack to play nicely with the RequireJS Text plugin?
Thanks!
Maybe try installing text-loader?
In order for something like 'text!../templates/contact_info.html' to "load" properly, since it is not JS, you need to install text-loader to get webpack to understand the syntax text!.
npm install text-loader --save-dev
humm...i just installed text-loaded and it seems we also have to change text! to text-loader!

Publish multiple Vuejs components in one project to npm using webpack

Im trying to publish a project to npm that contains two or more Vue components so i can import, register and use both components like this:
import Component1 from 'npm-package'
import Component2 from 'npm-package'
this is my webpack file:
const webpack = require('webpack');
const merge = require('webpack-merge');
const path = require('path');
var config = {
output: {
path: path.resolve(__dirname + '/dist/'),
},
module: {
loaders: [
{
test: /\.js$/,
loader: 'babel',
include: __dirname,
exclude: /node_modules/
},
{
test: /\.vue$/,
loader: 'vue'
},
{
test: /\.css$/,
loader: 'style!less!css'
}
]
},
externals: {
moment: 'moment'
},
plugins: [
new webpack.optimize.UglifyJsPlugin( {
minimize : true,
sourceMap : false,
mangle: true,
compress: {
warnings: false
}
} )
]
};
module.exports = [
merge(config, {
entry: path.resolve(__dirname + '/src/plugin.js'),
output: {
filename: 'vue-project.min.js',
libraryTarget: 'window',
library: 'VueProject',
}
}),
merge(config, {
entry: path.resolve(__dirname + '/src/index.js'),
output: {
filename: 'vue-project.js',
libraryTarget: 'umd',
library: 'vue-project',
umdNamedDefine: true
},
resolve: {
extensions: ['', '.js', '.vue'],
alias: {
'src': path.resolve(__dirname, '../src'),
'components': path.resolve(__dirname, '../src/components')
}
}
})
];
and this is the index.js file i'm using as the entry point for the build process
import Component1 from './components/folder1/Component1.vue'
import Component1 from './components/folder2/Component2.vue'
export default {
components: {
Component1,
Component2
}
}
The build process using npm run build works fine and i can publish the project to npm and install it using npm install. Importing and using it works fine to, but when i run my project i get the error:
failed to mount component: template or render function not defined.
All other posts o found regarding this error did not solve my problem, as none of them tried to export multiple components.
Both components work completely as intended when im publishing them in two different projects.
What am i missing here? Thanks in advance!
You don't need to export using the components property, you simply need to do:
export {
Component1,
Component2
}
You would then do:
import {Component1} from 'npm-package';
import {Component2} from 'npm-package';
or
import {Component1, Component2} from 'npm-package';
see: https://developer.mozilla.org/en-US/docs/web/javascript/reference/statements/export

Webpack not including ProvidePlugins

I have a small trial web application that I'm working on that uses the vue webpack template (https://github.com/vuejs-templates/webpack). I'm pretty new to webpack so I was assuming that I could add in to plugins a new webpack.ProvidePlugin and it would be available globally but when I do a npm run dev I get the following error:
/var/www/public/leadsStatsDashboard/liveleadstats/src/components/Hello.vue
18:17 error 'd3' is not defined no-undef
Which sounds like to me that it can't find the d3 reference. I'm no sure if there's some configuration I skipped over or what but any help would be appreciated. Here is the source for my files
Webpack.dev.conf.js:
var path = require('path')
var config = require('../config')
var utils = require('./utils')
var webpack = require('webpack')
var projectRoot = path.resolve(__dirname, '../')
module.exports = {
plugins: [
new webpack.ProvidePlugin({
d3: 'd3',
crossfilter: 'crossfilter',
dc: 'dc'
})
],
entry: {
app: './src/main.js'
},
output: {
path: config.build.assetsRoot,
publicPath: config.build.assetsPublicPath,
filename: '[name].js'
},
resolve: {
extensions: ['', '.js', '.vue'],
fallback: [path.join(__dirname, '../node_modules')],
alias: {
'src': path.resolve(__dirname, '../src'),
'assets': path.resolve(__dirname, '../src/assets'),
'components': path.resolve(__dirname, '../src/components'),
'd3': path.resolve(__dirname, '../bower_components/d3/d3.min.js'),
'crossfilter': path.resolve(__dirname, '../bower_components/crossfilter/crossfilter.min.js'),
'dc': path.resolve(__dirname, '../bower_components/dcjs/dc.js')
}
},
resolveLoader: {
fallback: [path.join(__dirname, '../node_modules')]
},
module: {
preLoaders: [
{
test: /\.vue$/,
loader: 'eslint',
include: projectRoot,
exclude: /node_modules/
},
{
test: /\.js$/,
loader: 'eslint',
include: projectRoot,
exclude: /node_modules/
}
],
loaders: [
{
test: /\.vue$/,
loader: 'vue'
},
{
test: /\.js$/,
loader: 'babel',
include: projectRoot,
exclude: /node_modules/
},
{
test: /\.json$/,
loader: 'json'
},
{
test: /\.html$/,
loader: 'vue-html'
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url',
query: {
limit: 10000,
name: utils.assetsPath('img/[name].[hash:7].[ext]')
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url',
query: {
limit: 10000,
name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
}
}
]
},
eslint: {
formatter: require('eslint-friendly-formatter')
},
vue: {
loaders: utils.cssLoaders()
}
}
Hello.vue
<template>
<div id="pieChartContainer">
</div>
</template>
<script>
export default {
data () {
return {
// note: changing this line won't causes changes
// with hot-reload because the reloaded component
// preserves its current state and we are modifying
// its initial state.
msg: 'Hello World! This is a test'
}
},
ready () {
console.log(d3.version)
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1 {
color: #42b983;
}
</style>
Your error isn't emitted from webpack, but from eslint.
I think the webpack part works as it should, in fact!
no-undef complains that you are using the global d3 without importing or defining it somewhere.
The good news is, that's easy to fix. Use any of the following three possibilities:
Just add the following block to your .eslintrc.js:
"globals": {
"d3": true
}
...or use eslint comments within the file that requires d3 implicitly (but that doesn't make much sense as you made it available globally and you would need to do this in every file you wish to use the global var):
/* eslint-disable no-undef */
...or you could relax the eslint rule in your .eslintrc.js config:
'rules': {
// all other rules...
'no-undef': 0
}
Additional links:
Direct link to the template's eslintrc file
The eslint 'standard' file the template extends
Further reading on eslint's no-undef rule

Resources