How do I compile multiple SCSS files in Webpack? - javascript

I have separate SCSS files I want to compile into separate CSS files. Here is a part of my Webpack config file:
module.exports = {
entry: ['./src/js/main.js', './src/scss/main.scss', './src/scss/additional.scss'],
output: {
filename: './assets/js/main.bundle.js',
},
plugins: [
new MiniCssExtractPlugin({
filename: './assets/css/main.bundle.css',
}),
],
modules: {...}
}
The example above will only compile main.scss and omit additional.scss. Here is what I tried:
module.exports = {
entry: {
main: ['./src/js/main.js', './src/scss/main.scss'],
additional: './src/scss/additional.scss',
},
output: {
filename: './assets/js/[name].bundle.js',
},
plugins: [
new MiniCssExtractPlugin({
filename: './assets/css/[name].bundle.css',
}),
],
modules: {...}
}
This kinda works, however this will also generate an additional.bundle.js which I don't need (I only need one JavaScript output and two CSS files). Any ideas?

Here is the solution I can up with. You basically need to create separate config objects for scss and everything else:
module.exports = [{
entry: {
main: ['./src/js/main.js'],
},
output: {
filename: './assets/js/[name].bundle.js',
},
modules: {...}
}, {
entry: {
main: ['./src/scss/main.scss'],
additional: ['./src/scss/additional.scss'],
},
output: {
filename: './.leftover/[name].bundle.js',
},
plugins: [
new MiniCssExtractPlugin({
filename: './assets/css/[name].bundle.css',
}),
],
modules: {...}
}]
then remove the .leftover directory on npm run build.
package.json:
"build": "webpack --mode production && del-cli dist/.leftover"
Not the cleanest solution, however that's the only one I can think of.

Related

Prevent Webpack from modifying javascript files

I have webpack in my plain HTML, CSS, and Javascript application. I use webpack to convert scss to CSS. I want my javascript to be the same untouched in my dist folder, as I want to edit it later my wordpress projects. Webpack is adding a lot of code, which makes the JS files hard to edit later. Here is my config.js
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const { HotModuleReplacementPlugin } = require("webpack");
const HtmlWebpackPartialsPlugin = require("html-webpack-partials-plugin");
module.exports = {
mode: "development",
entry: {
index: "./src/js/index.js",
about: "./src/js/about.js",
courses: "./src/js/courses.js",
contactUs: "./src/js/contact-us.js",
},
output: {
filename: "js/[name].bundle.js",
path: path.resolve(__dirname, "dist"),
assetModuleFilename: "images/[name][ext]",
},
devServer: {
static: { directory: path.join(__dirname, "dist") },
port: 9000,
hot: true,
},
plugins: [
new MiniCssExtractPlugin({
filename: "css/[name].css",
}),
new HtmlWebpackPlugin({
title: "Leads",
filename: "index.html",
template: "./src/pages/index.html",
chunks: ["index"],
}),
new HtmlWebpackPlugin({
title: "Leads About",
filename: "about-us.html",
template: "./src/pages/about-us.html",
chunks: ["about"],
}),
new HtmlWebpackPlugin({
title: "Courses",
filename: "courses.html",
template: "./src/pages/courses.html",
chunks: ["courses"],
}),
new HtmlWebpackPlugin({
title: "Contact Us",
filename: "contact-us.html",
template: "./src/pages/contact-us.html",
chunks: ["contactUs"],
}),
new HtmlWebpackPartialsPlugin({
path: path.join(__dirname, "./src/partials/footer.html"),
location: "partialfooter",
template_filename: [
"index.html",
"about-us.html",
"courses.html",
"contact-us.html",
],
}),
new HtmlWebpackPartialsPlugin({
path: path.join(
__dirname,
"./src/partials/components/infrastructure.html"
),
location: "infrastructure",
template_filename: [
"index.html",
"about-us.html",
"courses.html",
"contact-us.html",
],
}),
new HotModuleReplacementPlugin(),
],
module: {
rules: [
{
test: /\.js$/,
exclude: "/node_modules",
use: {
loader: "babel-loader",
options: {
presets: ["#babel/preset-env"],
},
},
},
{
test: /\.s[ac]ss$/i,
use: [
MiniCssExtractPlugin.loader,
// Creates `style` nodes from JS strings
// "style-loader",
// Translates CSS into CommonJS
"css-loader",
// Compiles Sass to CSS
"sass-loader",
],
},
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: "asset/resource",
},
],
},
optimization: {
minimize: false,
},
};
How can I get webpack to convert my sass files, but simply copy my JS files?
Perhaps you could use copy-webpack-plugin https://webpack.js.org/plugins/copy-webpack-plugin/ to copy files from your src static folder to your build destination folder. Roughly like this -
const CopyPlugin = require("copy-webpack-plugin");
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{ from: "source", to: "dest" },
{ from: "other", to: "public" },
],
}),
],
};
The code that Webpack adds can allow many features for JavaScript like transpiling ES6 JavaScript to ES5, bundling, code-splitting and dynamic imports. But if you don't need them a straight copy might do.

minify with raw bundler plugin in webpack

Objective is to concatenate src files to create a library file, and then create another version that's minified with sources maps. I'm using RawBundlerPlugin.
Following works like a charm! What's missing is how to generate another minified library.
const path = require("path");
const RawBundlerPlugin = require("webpack-raw-bundler");
module.exports = {
entry: "./src/header.txt",
output: {
filename: "MyLib.js",
path: path.resolve(__dirname, "dist")
},
module: {
rules: [
{ test: /\.txt$/, use: "raw-loader" }
]
},
plugins: [
new RawBundlerPlugin({
readEncoding: "utf-8",
bundles: [ "MyLib.js" ],
"MyLib.js": [
"src/header.txt",
"src/Product.js",
"src/Customer.js",
"src/copyright.txt"
]
})
],
mode: "none"
};
Question: How to include a minification build with sources maps using above configuration?
Or
maybe take the dist/MyLib.js and minify it to dist/MyLib.min.js through a subsequent process.
attempt https://webpack.js.org/plugins/uglifyjs-webpack-plugin/
optimization: {
minimizer: [new UglifyJsPlugin({
test: /\.js(\?.*)?$/i,
})],
},

Is there a way to expose module globally from Webpack DllPlugin vendor bundle?

Using Webpack 4, I'm creating a bundle and a vendors bundle. Vendor bundle contains jQuery and the code bundle references jquery using 'import * from jquery'. This works perfectly.
However, I now need to use a 3rd party (already minified) javascript file. That file expects jquery to be exposed as '$' on the global window object. My bundle needs to be loaded after the new minified file, also.
So I have:
<script src='./libs/jquery-3.2.1.min.js'></script>
<script src='../vendor.js'></script>
<script src="./libs/newMinifiedFile.js"></script>
<script src="../bundle.js"></script>
as my current workaround. The static jquery file links the $ objects to the global namespace, and then the vendor.js file allows me to keep using 'import' in my bundle.
So, how do I only load jquery once, and use it in both ways? This seems to be a slightly different problem than most I've seen online because of how I'm loading things.
Here's a small example of my configs right now:
const config = (isDebug) => {
const isDevBuild = isDebug;
const extractCSS = new MiniCssExtractPlugin({filename: 'vendor.css'});
const sharedConfig = {
mode: isDevBuild ? 'development' : 'production',
stats: { modules: false },
resolve: {
extensions: [ '.js' ]
},
module: {
rules: [
{ test: /\.(png|woff|woff2|eot|ttf|svg)(\?|$)/, use: 'url-loader?limit=100000' },
]
},
entry: {
vendor: [
'jquery'
],
},
output: {
publicPath: 'dist/',
filename: '[name].js',
library: '[name]_[hash]',
},
plugins: [
new webpack.NormalModuleReplacementPlugin(/\/iconv-loader$/, require.resolve('node-noop')) // Workaround for https://github.com/andris9/encoding/issues/16
]
};
const clientBundleConfig = merge(sharedConfig, {
output: {
path: path.join(__dirname, 'wwwroot', 'dist'),
pathinfo: false
},
module: {
rules: [
{
test: /\.css(\?|$)/, include: path.resolve(__dirname, "client"), exclude: [/webviewer/, /redux/, /helpers/],
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
minimize: isDevBuild,
sourceMap: isDevBuild
}
}
]
}
]
},
plugins: [
extractCSS,
new webpack.DllPlugin({
path: path.join(__dirname, 'wwwroot', 'dist', '[name]-manifest.json'),
name: '[name]_[hash]'
})
],
optimization: {
minimize: !isDevBuild,
removeAvailableModules: false,
removeEmptyChunks: false,
splitChunks: false,
},
});
And in my normal config I use:
new webpack.DllReferencePlugin({
context: __dirname,
manifest: require(path.join(__dirname, 'wwwroot', 'dist', 'vendor-manifest.json'))
})
So, I can find jquery in the global 'vendor_hash' object, but I can't get it to map it to $ no matter what I try (Most plugins seem to see that $ is never used in any of the code I'm supplying for the bundle and thus don't seem to include it). If I add something like this in my 'entry.js' file then it still doesn't work:
window.$ = window.jQuery = require("jquery");

Why webpack commonChunk duplicates packages between my bundles?

I want to create a vendor.bundle.js from my modules.
I configured webpack:
...
entry: {
app: ['./src/index.js'],
vendor: [
'axios',
'lodash',
'recharts',
'moment',
......
'react-select',
'react-tooltip',
'react-toggle',
'buffer',
'jstz',
'pikaday',
'qrcode-js',
'notie',
'tippy.js',
'react-dropzone',
'react-dd-menu',
'html-to-draftjs',
'react-virtualized',
'react-draft-wysiwyg',
'js-search',
'qr.js'
]
},
...
output: {
path: '/Users/ben/pro/qbpanel2.0/qbpanel-2.0/qbpanel/app/assets/javascripts',
publicPath: '/',
filename: 'bundle.js'
},
...
plugins: [
new BundleAnalyzerPlugin({
analyzerPort: 9998
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
filename: 'vendor.bundle.js',
path: '/Users/ben/pro/qbpanel2.0/qbpanel-2.0/qbpanel/app/assets/javascripts',
publicPath: '/',
minChunks: Infinity
}),
...
]
}
I expect to see all the packages listed in entry.vendor to end in the vendor.bundle.js, and for most of them it happens, but in my some of them show up in both bundle.js and vendor.bundle.js files.
Why?
bundle.js I was not expecting to find tippy.js or react-virtualized or lodash
vendor.bundle.js, there are the same packages that are in the bundle.js and I expect to be only here.
Which version of webpack are you using ?
To do what you're looking for, you can use the commonsChunkPluggin
The configuration could look like something like this in webpack 2:
plugins: [
new webpack.optimize.CommonsChunkPlugin({
name: ['node-modules'],
minChunks(module) {
const context = module.context;
return context && context.indexOf('node_modules') >= 0;
},
}),
new webpack.optimize.CommonsChunkPlugin({
name: ['vendor'],
chunks: ['node-modules'],
minChunks(module) {
return module.context && /.*\/axios|losash|allTheModulesYouWant.*/.test(module.context);
},
}),
]
This creates a chunk with all the node modules and takes out of it some of them (that you need to name) to put them into vendor

how to load moment.js into webpack

I want to load moment.js as a plugin into webpack. Does anyone know how to do so? I get the error "moment" is not defined when trying to call define('moment') in my backbone view
here's my webpack configuration:
app.use(webpackMiddleware(webpack({
context: __dirname + '/src',
entr: './admin-entry.js',
entry: {
'admin-entry': './admin-entry.js',
'admin-login': './admin-login.js'
},
output: {
path: '/webpack',
publicPath: '/webpack',
filename: '[name].js'
},
module: {
noParse: [
new RegExp(jqueryPath),
new RegExp(lodashPath),
new RegExp(qPath),
new RegExp(cookiePath),
new RegExp(momentPath),
new RegExp(dateRangePickerPath)
]
},
resolve: {
alias: {
'jquery': jqueryPath,
'lodash': lodashPath,
'underscore': lodashPath,
'backbone': backbonePath,
'cookie': cookiePath,
'daterangepicker': dateRangePickerPath,
'moment': momentPath,
'q': qPath
},
modulesDirectories: [
'node_modules'
]
},
devtool: 'eval-source-map',
plugins: [
new webpack.SourceMapDevToolPlugin('webpack/[file].map', null, '[absolute-resource-path]', '[absolute-resource-path]')
]
}), {
noInfo: false,
quiet: false,
lazy: false,
// switch into lazy mode
// that means no watching, but recompilation on every request
watchOptions: {
aggregateTimeout: 300,
poll: true
},
publicPath: '/webpack',
// public path to bind the middleware to
// use the same as in webpack
stats: {
colors: true
}
}));
At first, ensure that you install moment with npm command
npm install moment
Now you should have moment in your node_modules folder. Then you should add moment to your project as a global variable so you should change Webpack to resolve it for you.To do this change your webpack.config.js file as below:
plugins: [
....
new webpack.ProvidePlugin({
moment : 'moment'
})
....
]

Categories

Resources