... despite my configuration file telling it not to. It is a simple file only handling a few file types as seen below. I am using webpack 5.7.0, the current latest version.
const jsx = {
test: /\.jsx?/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['#babel/preset-react']
}
}
};
const file_types = {
rules: [
jsx
]
};
const entry = '/Users/c/top/tiny/index.jsx';
const output = {
filename: 'bundle.js',
path: '/Users/c/top/tiny/dist'
};
const config_obj = {
entry: entry,
output: output,
module: file_types
};
module.exports = (env) => {
return config_obj;
};
Related
I just spent 3 hours putting this line:
exclude: ['./src/assets/sass']
in 20 different places. Please tell me where this should go?
Here is my current setup for the css-loader (util.js):
'use strict'
const path = require('path')
const config = require('../config')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const packageConfig = require('../package.json')
exports.assetsPath = function (_path) {
const assetsSubDirectory = process.env.NODE_ENV === 'production'
? config.build.assetsSubDirectory
: config.dev.assetsSubDirectory
return path.posix.join(assetsSubDirectory, _path)
}
exports.cssLoaders = function (options) {
options = options || {}
const cssLoader = {
loader: 'css-loader',
options: {
sourceMap: options.sourceMap
}
}
const postcssLoader = {
loader: 'postcss-loader',
options: {
sourceMap: options.sourceMap
}
}
// generate loader string to be used with extract text plugin
function generateLoaders (loader, loaderOptions) {
const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader]
if (loader) {
loaders.push({
loader: loader + '-loader',
// exclude: ['./src/assets/sass'],
options: Object.assign({}, loaderOptions, {
sourceMap: options.sourceMap
})
})
}
// Extract CSS when that option is specified
// (which is the case during production build)
if (options.extract) {
return ExtractTextPlugin.extract({
use: loaders,
fallback: 'vue-style-loader'
})
} else {
return ['vue-style-loader'].concat(loaders)
}
}
// https://vue-loader.vuejs.org/en/configurations/extract-css.html
return {
css: generateLoaders(),
postcss: generateLoaders(),
less: generateLoaders('less'),
sass: generateLoaders('sass', { indentedSyntax: true }),
scss: generateLoaders('sass'),
stylus: generateLoaders('stylus'),
styl: generateLoaders('stylus')
}
}
// Generate loaders for standalone style files (outside of .vue)
exports.styleLoaders = function (options) {
const output = []
const loaders = exports.cssLoaders(options)
for (const extension in loaders) {
const loader = loaders[extension]
output.push({
test: new RegExp('\\.' + extension + '$'),
exclude: ['./src/assets/sass'],
use: loader
})
}
return output
}
exports.createNotifierCallback = () => {
const notifier = require('node-notifier')
return (severity, errors) => {
if (severity !== 'error') return
const error = errors[0]
const filename = error.file && error.file.split('!').pop()
notifier.notify({
title: packageConfig.name,
message: severity + ': ' + error.name,
subtitle: filename || '',
icon: path.join(__dirname, 'logo.png')
})
}
}
Here is what my base webpack file looks like:
'use strict'
const path = require('path')
const utils = require('./utils')
const config = require('../config')
const vueLoaderConfig = require('./vue-loader.conf')
function resolve (dir) {
return path.join(__dirname, '..', dir)
}
module.exports = {
context: path.resolve(__dirname, '../'),
entry: {
app: ['babel-polyfill','./src/main.js']
},
output: {
path: config.build.assetsRoot,
filename: '[name].js',
publicPath: process.env.NODE_ENV === 'production'
? config.build.assetsPublicPath
: config.dev.assetsPublicPath
},
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'vue$': 'vue/dist/vue.esm.js',
'#': resolve('src'),
}
},
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
options: vueLoaderConfig
},
{
test: /\.js$/,
loader: 'babel-loader',
include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')],
},
// {
// test: /\.scss$/,
// exclude: ['./src/assets/sass']
// },
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('img/[name].[hash:7].[ext]')
}
},
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('media/[name].[hash:7].[ext]')
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
}
}
]
},
node: {
// prevent webpack from injecting useless setImmediate polyfill because Vue
// source contains it (although only uses it if it's native).
setImmediate: false,
// prevent webpack from injecting mocks to Node native modules
// that does not make sense for the client
dgram: 'empty',
fs: 'empty',
net: 'empty',
tls: 'empty',
child_process: 'empty'
}
}
Here is the vue-webpack file:
'use strict'
const utils = require('./utils')
const config = require('../config')
const isProduction = process.env.NODE_ENV === 'production'
const sourceMapEnabled = isProduction
? config.build.productionSourceMap
: config.dev.cssSourceMap
module.exports = {
loaders: utils.cssLoaders({
sourceMap: sourceMapEnabled,
extract: isProduction
}),
cssSourceMap: sourceMapEnabled,
cacheBusting: config.dev.cacheBusting,
transformToRequire: {
video: ['src', 'poster'],
source: 'src',
img: 'src',
image: 'xlink:href'
}
}
Presumably this line should go in one of these files unfortunately it is not preventing webpack from attempting to build it (and therefore failing to do so)
Turns out after much experimentation that if I removed this line from the first snippet:
scss: generateLoaders('sass'),
The reason seems to be that even though the files in this directory are never used in my project, the loader attempts to load them because of the file name, so by not having a loader it does not attempt that and no other errors are thrown since the file is not used.
Presumably if one wanted to keep the loader and exclude a specific directory then you would need to put in a condition on this section in the first snippet:
for (const extension in loaders) {
const loader = loaders[extension]
//enter your condition here, i.e. if(loader === something) then push an object
// with "exclude"
output.push({
test: new RegExp('\\.' + extension + '$'),
exclude: ['./src/assets/sass'],
use: loader
})
}
I'm trying to use webpack to bundle my backend code. It's currently using vanilla node.js where I'm using module.exports.x, and when I run webpack, it also outputs the export line i.e. module.exports.x. Now the problem is when I run nodemon on the file, it gives me the error TypeError: Cannot set property 'x' of undefined.
What's my resolution here?
my config file.
"use strict"
const path = require("path")
// const utils = require("./utils")
// const config = require("../config")
var fs = require("fs")
const NodemonPlugin = require("nodemon-webpack-plugin")
const nodeExternals = require("webpack-node-externals")
function resolve(dir)
{
return path.join(__dirname, "..", dir)
}
module.exports = {
context: path.resolve(__dirname, "../"),
entry: "./src/server/server.js",
output: {
path: path.resolve(__dirname, "../src/server"),
filename: "server-webpack.js",
},
plugins: [
new NodemonPlugin(),
],
resolve: {
extensions: [".js",".ts", ".tsx"],
alias: {
"#": resolve("src"),
"#": resolve("src/server")
}
},
devtool: "#inline-source-map",
module: {
rules: [
{
test: /\.js$/,
loader: "babel-loader",
include: [resolve("src"), resolve("test")]
},
{
test: /\.tsx?$/,
loader: "ts-loader",
},
]
},
externals: [
nodeExternals()
],
target: "node"
}
In my app.js file I have the following event inside a function where I import another module (same as in the docs) using the lazy-loading technique:
button.onclick = e => import(/* webpackChunkName: "print" */ './print').then(module => {
var print = module.default;
print();
});
And in my webpack config I set up this (besides Babel, SASS loaders, etc):
const path = require('path');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
module.exports = {
watch: true,
entry: {
main: ['babel-polyfill', './src/js/app.js','./src/sass/main.sass']
},
output: {
chunkFilename: '[name].bundle.js',
path: path.resolve(__dirname, "dist"),
filename: '[name].js',
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ["babel-preset-env", "babel-preset-stage-0"]
}
}
},
{
test: /\.sass$/,
exclude: /node_modules/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: [
'css-loader',
{
loader: 'sass-loader',
query: {
sourceMap: false,
},
},
],
}),
},
]
}
}
The problem is the path "./print" is from my "src" folder and not from my "dist" folder, where webpack puts all the bundles, so I get a 404 error. If I change the path to "./dist/print" then the webpack build will crash.
Am I missing a webpack configuration?
Edit:
Folder structure:
src
js
app.js
print.js
dist
main.bundle.js
print.bundle.js
You don't have to treat with the modules path in dist folder, only in src folder.
There is two solutions I think :
1/ Specify src path in your import statement :
button.onclick = e => import(/* webpackChunkName: "print" */ './src/js/print').then(module => {
var print = module.default;
print();
});
2/ Personally, What I usually do is to add src folder to resolved paths in config file:
resolve: {
modules: [
path.resolve('./node_modules'),
path.resolve('./src/js')
],
extensions: ['.json', '.js']
},
Your code should then work without changing a line.
Entry file will build literally just fine, but the error occurs on client side, which makes the whole bundle file doesn't work with this issue Uncaught TypeError: Cannot read property 'Blob' of undefined
and i have attached the webpack.config.js which i have tried too
const path = require('path')
const webpack = require('webpack')
const HtmlPlugin = require('html-webpack-plugin')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const config = {
entry: './src/main-entry.js',
output: {
path: path.resolve(__dirname, 'views/dist'),
filename: 'bundle.js'
},
module: {
rules: [
{ test: /\.(png|woff|woff2|eot|ttf|svg|gif)$/, loader: 'url-loader?limit=100000' },
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
use: 'css-loader', fallback: 'style-loader'
})
},
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/
}
]
},
plugins: [
new ExtractTextPlugin('bundle.css'),
new webpack.optimize.UglifyJsPlugin({
include: /\.min\.js$/,
minimize: true
})
]
}
module.exports = config
I am using webpack latest version. But i don't know why this is happening? can you help me?
I have a Webpack flow where multiple configurations are merged depending on the type of build. I'm still a webpack newbie but getting the hang of it - but ran into a problem.
With the setup I have som css loaders which are used in my common flow - that is on every build. Now I need some loaders only used for production builds. With my current setup the loaders for production is never used - but if I outcomment the loaders in my common setup the production loaders are run.
Is there a way to merge rules for css from different configurations?
My webpack.config.js
const path = require('path');
const webpackMerge = require('webpack-merge');
const commonPartial = require('./webpack/webpack.common');
const clientPartial = require('./webpack/webpack.client');
const serverPartial = require('./webpack/webpack.server');
const prodPartial = require('./webpack/webpack.prod');
const { getAotPlugin } = require('./webpack/webpack.aot');
module.exports = function (options, webpackOptions) {
options = options || {};
webpackOptions = webpackOptions || {};
if (options.aot) {
console.log(`Running build for ${options.client ? 'client' : 'server'} with AoT Compilation`)
}
let serverConfig = webpackMerge({}, commonPartial, serverPartial, {
entry: options.aot ? { 'main-server' : './Client/main.server.aot.ts' } : serverPartial.entry, // Temporary
plugins: [
getAotPlugin('server', !!options.aot)
]
});
let clientConfig = webpackMerge({}, commonPartial, clientPartial, {
plugins: [
getAotPlugin('client', !!options.aot)
]
});
if (options.prod) {
// Change api calls prior to packaging due to the /web root on production
clientConfig = webpackMerge({}, prodPartial, clientConfig);
serverConfig = webpackMerge({}, prodPartial, serverConfig);
}
const configs = [];
if (!options.aot) {
configs.push(clientConfig, serverConfig);
} else if (options.client) {
configs.push(clientConfig);
} else if (options.server) {
configs.push(serverConfig);
}
return configs;
}
My webpack.common.js
const { root } = require('./helpers');
const path = require('path');
const ExtractTextPlugin = require("extract-text-webpack-plugin");
/**
* This is a common webpack config which is the base for all builds
*/
const extractBeneath = new ExtractTextPlugin('../assets/stylesheets/beneath.css');
const extractSkolePlan = new ExtractTextPlugin('../assets/stylesheets/skoleplan.css');
const source = path.resolve(__dirname, 'Client');
const appDirectory = path.resolve(source, 'app');
module.exports = {
devtool: 'source-map',
resolve: {
extensions: ['.ts', '.js']
},
output: {
filename: '[name].js',
publicPath: '/dist/' // Webpack dev middleware, if enabled, handles requests for this URL prefix
},
module: {
rules: [
{ test: /\.ts$/, loader: '#ngtools/webpack' },
{
//***** This is working nicely *****
test: /\.css$/,
exclude: appDirectory,
use: extractSkolePlan.extract({
fallback: 'to-string-loader',
use: 'css-loader?sourcemap'
})
},
{
//***** This is working nicely too *****
test: /\.css$/,
include: appDirectory,
use: 'raw-loader'
},
{ test: /\.html$/, loader: 'html-loader' },
{
test: /\.less$/,
use: extractBeneath.extract({
fallback: 'to-string-loader',
use: ['css-loader', 'less-loader']
})
},
{ test: /\.(woff2?|ttf|eot|svg)$/, loader: 'url-loader?limit=10000' },
{ test: /\.(png|jpg|jpeg|gif)$/, loader: 'url-loader?limit=25000' }
]
}
,
plugins: [
extractSkolePlan,
extractBeneath
]
};
And my webpack.prod.js
const { root } = require('./helpers');
const path = require('path');
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const StringReplacePlugin = require("string-replace-webpack-plugin");
const source = path.resolve(__dirname, 'Client');
const appDirectory = path.resolve(source, 'app');
/**
* This is a prod config to be merged with the Client config
*/
module.exports = {
module: {
rules: [
{
test: /\.ts$/,
loader: StringReplacePlugin.replace({
replacements: [
{
pattern: /return window.location.origin;/ig,
replacement: function() {
console.log(' Her er javascript replaced');
return 'return window.location.origin + \'/web\'';
}
}
]
})
},
{
//***** This is never loaded *****
test: /\.css$/,
exclude: appDirectory,
use: StringReplacePlugin.replace({
replacements: [
{
pattern: /assets/ig,
replacement: function() {
console.log('Her er css skiftet');
return '/web/assets/martin';
}
}
]
})
}
]
},
plugins: [
// an instance of the plugin must be present
new StringReplacePlugin()
]
};
Any help is appreciate - thanks :-)
I am not familiar with the package you are using, webpack-merge, but when testing, it is similar to:
Object.assign({}, {foo: 'a'}, {foo: 'b'}) // => {foo: 'b'}
It gives priority to the objects from right to left. So in your example, it should be:
if (options.prod) {
// Change api calls prior to packaging due to the /web root on production
clientConfig = webpackMerge({}, clientConfig, prodPartial);
serverConfig = webpackMerge({}, serverConfig, prodPartial);
}
With prodPartial at the right, in order to get preference over the commonPartial inside serverConfig and clientConfig.
However, I would advise to make these three configuration files easier to reason about by having several imports, e.g. module.exports.output, module.exports.rules, and do the merging manually in the main config file.