Can Babel Apply to Selected Files in Webpack Config? - javascript

Here is my webpack.config (using webpack 3) below
I have several .js files in entry.
I'd like to find a way to transpile select .js files through babel while excluding others.
I found a way to include all the .js files in the js/ directory through babel.. But how can I exclude the .js files in js/vendor?
const path = require('path');
const webpack = require('webpack');
module.exports = {
context: __dirname,
entry: {
dataviz : '../js/entry-dataviz.js',
template : '../js/entry-viz-template.js',
abc : '../js/entry-viz-abc.js',
sample: '../js/sample.js',
vendor: [
'../js/vendor/bootstrap.min.js',
'../js/vendor/history.js',
'../js/vendor/history.adapter.jquery.js'
]
},
output: {
filename: '[name]-[chunkhash].js'
},
module: {
rules: [
{
test: /\.js$/,
include: [
path.resolve(__dirname, '../js'), <-- including everything in js/directory
],
use: {
loader: 'babel-loader',
options: { presets: 'es2015'}
}
}
]
},

include can accept a function:
include: function (modulePath) {
// inside `js` folder but not `js/vendor`
return true;
}

Related

Webpack4 how to load images and custom javascript directly from HTML file?

I want to load images directly from HTML with Webpack 4 and add custom Javascript files to my HTML file but both files inspected at console show Not found 404.
How to properly load images and Javascipt files with Webpack 4?
My Webpack 4 config file:
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
module.exports = {
entry: {
main: "./src/index.js"
},
output: {
path: path.join(__dirname, "../build"),
filename: "[name].bundle.js"
},
mode: "development",
devServer: {
contentBase: path.join(__dirname, "../build"),
compress: true,
port: 3000,
overlay: true
},
devtool: "cheap-module-eval-source-map",
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader" // transpiling our JavaScript files using Babel and webpack
}
},
{
test: /\.(sa|sc|c)ss$/,
use: [
"style-loader", // creates style nodes from JS strings
"css-loader", // translates CSS into CommonJS
"postcss-loader", // Loader for webpack to process CSS with PostCSS
"sass-loader" // compiles Sass to CSS, using Node Sass by default
]
},
{
test: /\.(png|svg|jpe?g|gif)$/,
use: [
{
loader: "file-loader", // This will resolves import/require() on a file into a url and emits the file into the output directory.
options: {
name: "[name].[ext]",
outputPath: "assets",
}
},
]
},
{
test: /\.html$/,
use: {
loader: "html-loader",
options: {
attrs: ["img:src", ":data-src"],
minimize: true
}
}
}
]
},
plugins: [
// CleanWebpackPlugin will do some clean up/remove folder before build
// In this case, this plugin will remove 'dist' and 'build' folder before re-build again
new CleanWebpackPlugin(),
// The plugin will generate an HTML5 file for you that includes all your webpack bundles in the body using script tags
new HtmlWebpackPlugin({
template: "./src/index.html",
filename: "index.html"
}),
]
My webpack.prod.js file:
const path = require("path");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const CompressionPlugin = require("compression-webpack-plugin");
const TerserJSPlugin = require("terser-webpack-plugin");
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-
plugin");
const BrotliPlugin = require("brotli-webpack-plugin");
const PurgecssPlugin = require('purgecss-webpack-plugin');
const glob = require("glob");
module.exports = {
entry: {
main: "./src/index.js"
},
output: {
path: path.join(__dirname, "../build"),
filename: "[name].[chunkhash:8].bundle.js",
chunkFilename: "[name].[chunkhash:8].chunk.js"
},
mode: "production",
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader" // transpiling our JavaScript files using
Babel and webpack
}
},
{
test: /\.(sa|sc|c)ss$/,
use: [
MiniCssExtractPlugin.loader,
"css-loader", // translates CSS into CommonJS
"postcss-loader", // Loader for webpack to process CSS with
PostCSS
"sass-loader" // compiles Sass to CSS, using Node Sass by
default
]
},
{
test: /\.(png|svg|jpe?g|gif)$/,
use: [
{
loader: "file-loader", // This will resolves import/require()
on a file into a url and emits the file into the output directory.
options: {
name: "[name].[ext]",
outputPath: "assets/"
}
},
]
},
{
test: /\.html$/,
use: {
loader: "html-loader",
options: {
attrs: ["img:src", ":data-src"],
minimize: true
}
}
}
]
},
optimization: {
minimizer: [new TerserJSPlugin(), new OptimizeCSSAssetsPlugin()],
splitChunks: {
cacheGroups: {
commons: {
test: /[\\/]node_modules[\\/]/,
name: "vendors",
chunks: "all"
}
},
chunks: "all"
},
runtimeChunk: {
name: "runtime"
}
},
plugins: [
// CleanWebpackPlugin will do some clean up/remove folder before build
// In this case, this plugin will remove 'dist' and 'build' folder
before re-build again
new CleanWebpackPlugin(),
// PurgecssPlugin will remove unused CSS
new PurgecssPlugin({
paths: glob.sync(path.resolve(__dirname, '../src/**/*'), { nodir:
true })
}),
// This plugin will extract all css to one file
new MiniCssExtractPlugin({
filename: "[name].[chunkhash:8].bundle.css",
chunkFilename: "[name].[chunkhash:8].chunk.css",
}),
// The plugin will generate an HTML5 file for you that includes all
your webpack bundles in the body using script tags
new HtmlWebpackPlugin({
template: "./src/index.html",
filename: "index.html"
}),
My project nesting:
--Build
--src
----html
----js
----styles
----assets
------images
I want that files would load simply:
<img src="assets/images/myimage.jpg">
<srcipt src="js/custom.js"></script>
Any help would be appreciated.
Ironically this is my second project with Webpack 4 and this time I can't fix this issue, the first time there was no problem.
This is how img work in Webpack:
<img src=require("./assets/images/myimage.jpg")>
if you use "require" with file-loader, you need to add default.
<img src=require("./assets/images/myimage.jpg").default>
For script tag, src should be your output bundle.js file; because Webpack writes all the code into the bundle.js with the help of Babel. So when browser request html, browser will have only one Javascript file which is the bundle to download. That is the whole point of bundle, smaller bundle.js is better for performance.
// According to your Webpack config, it is main.bundle.js
<srcipt src="main.bundle.js"></script>
but in order to browser to use this main.bundle.js, it has to be publicly available. So you need express to define the public folder, when browser looks for main.bundle.js, you app will be looking into the public folder and if that file exists, it will ship it to the browser.
const express = require("express");
const server = express();
const staticMiddleware = express.static("build");
server.use(staticMiddleware);

How to bundle assets folder fully - webpack

I am building a Web Application using MEAN stack.
I am using webpack to bundle my files.
In my project, I have two folders called 1.public/assets (in this assets folder I have separate folders called CSS, js, etc.. which contains various js and CSS.
and I have a folder called 2.client (in this I have my AngularJs code like controllers.js, services.js)
I am using webpack to bundle my client code.
const path = require('path');
const glob = require('glob');
const CleanWebpackPlugin = require('clean-webpack-plugin');
// const CopyWebpackPlugin = require('copy-webpack-plugin');
const outputDirectory = 'dist';
module.exports = {
mode: 'development',
target: 'web',
entry: {
app: glob.sync('./client/*.js'),
},
output: {
path: path.resolve(__dirname, outputDirectory),
filename: '[name].bundle.js',
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
query: {
presets: ['env', 'stage-0'],
},
},
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader'],
},
{
test: /\.(png|woff|woff2|eot|ttf|svg|jpg)$/,
loader: 'url-loader?limit=100000',
},
],
},
devServer: {
port: 3005,
open: false,
disableHostCheck: true,
proxy: {
'/': 'http://localhost:8005',
},
},
plugins: [
new CleanWebpackPlugin([outputDirectory]),
// new CopyWebpackPlugin([
// { from: 'public/assets' },
// ]),
],
};
I am just bundling my client folder and compiling that into app.bundle.js,
How to compile assets?
NOTE: I am using AngularJs v1.
Webpack starts from each entry point (you could have more than one entry point) and creates a dependency graph. Files/assets are added to the dependency graph when you have imported them into your application through the use of require and import statements.
What is not clear in your question is the relationship between your client folder and your public/assets folder, and whether they are linked. However, if none of the files in your client folder depend upon (require, import) any of the assets in your public/assets folder then they won't be in webpack's dependency graph, and therefore won't be transpiled and bundled.

How to bundle JS and CSS file independently with Webpack?

I have a few JS and SCSS files. I need Webpack 4 to bundle each JS entry to one JS file and each SCSS entry to one CSS file. The JS files don't import the SCSS files. I try to do it with the following webpack.config.js:
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
entry: {
scriptFoo: './src/js/scriptFoo.js',
scriptBar: './src/js/scriptBar.js',
// ...
styleBaz: './src/css/styleBaz.scss',
styleBaq: './src/css/styleBaq.scss'
// ...
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: 'babel-loader'
},
{
test: /\.(scss|sass)$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'postcss-loader',
'sass-loader'
]
}
]
},
output: {
filename: '[name].js',
path: path.resolve(__dirname, 'dist')
},
plugins: [
new MiniCssExtractPlugin({
filename: '[name].css'
})
]
};
It works fine, Webpack puts the compiled files to the dist directory. But it also creates an excess dummy JS file for each SCSS file in the dist directory:
webpack.config.js
src/
js/
scriptFoo.js
scriptBar.js
...
css/
styleBaz.scss
styleBaq.scss
...
dist/
scriptFoo.js
scriptBar.js
...
styleBaz.css
styleBaz.js // Excess
styleBaq.css
styleBaq.js // Excess
...
How to make Webpack not to create the excess JS files?
Use the ignore-emit-webpack-plugin Webpack plugin to not create the excess file. First install it by running in a console:
npm install --save-dev ignore-emit-webpack-plugin
Then add it to your Webpack configuration:
const IgnoreEmitPlugin = require('ignore-emit-webpack-plugin');
module.exports = {
// ...
plugins: [
// ...
new IgnoreEmitPlugin(['styleBaz.js', 'styleBaq.js']) // Or simply: new IgnoreEmitPlugin(/^style.*\.js$/)
]
};
It is because for each property in the entry object ,The js file is created in output destinations.
output: {
filename: '[name].js',
path: path.resolve(__dirname, 'dist')
},
Webpack creating dummy js when css is an entry point is a known bug, which has not been fixed yet.
Also having multiple entry files in the entry configuration will also affect treeshaking capabilties

Webpack - Folder Access Outside Application Folder

I have code base, the folder structure for which looks like this :
|- build\
|- node_modules\
|- apps\
|--- app_no_1\
|----- index.js
|- src\
|--- modules\
|----- form-login\
|------- Form.jsx
|- package.json
|- webpack.config.js
....
The app_no_1\ folder holds the index file for its React app. However, the modules are sat within the src\ folder. When I import the component from the src directory into the app, I get the error:
bundle.js:41448 Uncaught Error: Module parse failed: Unexpected token (15:18)
You may need an appropriate loader to handle this file type.
| // );
Is there some webpack configuration option I am missing which is required for access to files outside the app's folder? My webpack.config.js is this:
const path = require('path');
const merge = require('merge');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const PATHS = {
app: path.join(__dirname, 'apps'),
appAthenaTrader: path.join(__dirname, 'apps/athenaTrader'),
appAthenaFinancier: path.join(__dirname, 'apps/athenaFinancier'),
build: path.join(__dirname, 'build'),
modules: path.join(__dirname, 'src/modules')
};
const common = {
output: {
path: PATHS.build,
publicPath: '/',
filename: 'bundle.js'
},
resolve: {
alias: {
modules: PATHS.modules
},
extensions: ['.js', '.jsx', '.json'],
modules: [PATHS.modules, 'node_modules']
},
module: {
rules: [
{
test: /\.jsx?$/,
include: PATHS.app,
use: [
{
loader: 'babel-loader',
options: {
cacheDirectory: true
}
}
]
},
{
test: /\.scss$/,
include: PATHS.app,
use: [
{
loader: 'style-loader'
},
{
loader: 'css-loader'
},
{
loader: 'sass-loader'
}
]
},
{
test: /\.(jpg|png)$/,
include: PATHS.app,
use: {
loader: 'file-loader?name=[name].[ext]'
}
}
]
},
plugins: [
new HtmlWebpackPlugin({
title: 'Satoshi Ltd - Athena'
})
]
};
const generateEntry = env => {
const entryVariable = {
entry: {
app: ''
}
};
if (env.app === 'athena-trader') {
entryVariable.entry.app = PATHS.appAthenaTrader;
} else if (env.app === 'athena-financier') {
entryVariable.entry.app = PATHS.appAthenaFinancier;
// } else ...
}
return entryVariable;
};
const devServer = {
devServer: {
stats: 'errors-only',
host: process.env.HOST || 'localhost',
port: process.env.PORT || 3000
},
devtool: 'inline-source-map'
};
const generateConfig = env => {
const entry = generateEntry(env);
if (env.profile === 'development') {
return merge(common, entry, devServer);
}
return merge(common, entry);
};
module.exports = generateConfig(process.env);
I should note that when the folder is brought inside the app_no_1, the app functions fine, i.e. it is able to execute the component & display it. However, the above folder structure is not being accepted for the apps.
The issue is in your babel-loader configuration. Webpack is complaining that it doesn't know how to parse your files (I'm assuming it's JSX).
In your configuration, you have:
module: {
rules: [
{
test: /\.jsx?$/,
include: PATHS.app,
use: [
{
loader: 'babel-loader',
options: {
cacheDirectory: true
}
}
]
},
// ...
]
include tells webpack to use babel-loader on any files located inside PATHS.app. When it looks at your files located in PATHS.modules, it doesn't use babel-loader. This is when webpack shows that Module parse failed error.
To fix this, you can update your include value to something like this:
include: [PATHS.app, PATHS.modules]
An alternative is to use exclude instead of include.
// assuming you want to only ignore node_modules
exclude: /node_modules/
I also made a barebones example of this on Github.

Extracting sass as css using webpack

First. I know questions like this were asked, but I am missing something to understand them. I am trying to compile scss to css. And I would like webpack to basically do the same as sass app.scss : app.css. I tried to configure it using extract-text-webpack-plugin, but I am doing something wrong or missing smth.
It worked if I include(app.scss) in app.js but this makes no sense because if anyone has disabled JavaScript the styles won't work.
This is my webpack.config.js file. I have no idea how to do it.
const webpack = require("webpack");
const ExtractTextPlugin = require("extract-text-webpack-plugin");
var jsConfig = {
entry: "./_dev/scripts/app.js",
output: { filename: "./scripts/bundle.js" },
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader"
}
]
}
};
var scssConfig = {
entry: "./_dev/scss/app.scss",
output: { filename: "./content/app.css" },
module: {
rules: [
{
test: /\.scss$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: "css-loader"
})
}
]
},
plugins: [
new ExtractTextPlugin({filename:"./_dev/scss/app.scss"}),
]
};
var config = [scssConfig, jsConfig];
module.exports = config;
Edit: I also found this. This series would have helped with all my questions so if you have similar questions make sure to read it before asking!
https://codeburst.io/simple-beginner-guide-for-webpack-2-0-from-scratch-part-v-495dba627718
You need to include your app.scss for webpack to be able to find your scss references because webpack will traverse your project and apply loaders to all files it can find through references starting from app.js recursively down. If you don't have references to app.scss somewhere in the project webpack can't find it and it won't build it. So in the entry of you project (assume it is app.js) you need to do this:
import 'relative/path/to/styles/app.scss';
But it doesn't mean that those who don't have js enabled won't receive your styles. You need to include app.scss only for the build phase of your project, after that your styles will be included in html and will be loaded even for those without js enabled.
webpack concepts section explains how webpack finds dependencies based on your entry point building its internal graph of dependencies.
Update:
There is a way that allows you to not add your app.scss in your js. You can include multiple files in your entry object in your webpack config. Here is an example of how configuration might look in your case:
const webpack = require("webpack");
const ExtractTextPlugin = require("extract-text-webpack-plugin");
var config = {
entry: {
main: [
"./_dev/scripts/app.js",
"./_dev/scss/app.scss"
],
},
output: {
path: './scripts',
filename: "bundle.js"
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader"
},
{
test: /\.(css|scss)/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: ['css-loader', 'sass-loader']
})
}
]
},
plugins: [
new ExtractTextPlugin("./_dev/scss/app.scss"),
]
};
module.exports = config;
More information available on SO question webpack-multiple-entry-points-sass-and-js.
You also have incorrect configuration of ExtractTextPlugin in webpack. You are placing the whole path in the option for filename, which is not correct. In your case it should look like this:
plugins: [
new ExtractTextPlugin("./_dev/scss/app.css"),
]

Categories