Webpack in ES6 create an empty bundle - javascript

I am trying to use webpack in ES6 but there is something wrong, the bundle is created but it seems to contain nothing.
src/index.js
console.log("inside");
export const testData = 15;
webpack.prod.js
import path from "path";
import HtmlWebpackPlugin from "html-webpack-plugin";
export default {
entry: {
myApp: './src/index.js',
},
plugins: [
new HtmlWebpackPlugin({
title: 'Production',
}),
],
output: {
filename: '[name].bundle.js',
path: path.resolve(".", './dist'),
clean: true,
module: true,
libraryTarget: 'umd'
},
module: {
rules: [
{
test: /\.(js)$/,
exclude: /node_modules/,
use: "babel-loader",
include: path.resolve(".", "src")
}
]
},
mode: "production",
devtool: "source-map"
};
package.json
{
...
"scripts": {
"build": "webpack --config ./webpack.prod.js"
},
"devDependencies": {
"html-webpack-plugin": "5.5.0",
"path": "0.12.7",
"webpack": "^5.72.0",
"webpack-cli": "^4.9.2",
"webpack-dev-middleware": "5.3.1",
"webpack-dev-server": "4.8.1",
"webpack-merge": "^5.8.0",
"babel-core": "6.26.3",
"babel-loader": "8.2.5",
"babel-preset-es2015": "6.24.1"
},
"type": "module"
...
After creating the bundle, the index.html file inside the dist folder I insert a log but when it starts does not show the log and gives me the error testData is not defined
dist/index.html
...
<head>
<title>Production</title>
<script defer="defer" src="myApp.bundle.js"></script>
<script>
window.addEventListener("load", () => {
console.log( "window load" );
console.log( "testData" );
console.log( testData ); // <--------------------- it give the error
}, false)
</script>
</head>
...```

Since you are exporting const value, which get disolve in build and webpack optimization process. It's better to make it part of some module and export it.
With few modifications you can get what you are expecting.
index.js
export default {
fuel: 100,
passengers: 7,
target: 'mars',
launch: function () {
console.log('Saturn VI ready to launch');
},
reportPorblem: function () {
return 'Houston, we have a problem';
},
land: function () {
console.log('Saturn VI landed successfully')
}
};
Remove module: true from output, what it is you can learn here.
output.library
Also you need to make few to changes to output in webpack. Remove libraryTarget and add library to output.
With library name here it's MyLibrary you can access exported details. Type property set how module to be exposed, webpack allow you to expose your module with certain standards with libraryTarget or library.type. Here its expected to be var.
webpack.prod.js
output: {
...
library: {
name: 'MyLibrary',
type: 'var',
export: 'default',
},
},
There are quite few options supported by webpack.
libraryTarget: "umd", enum
libraryTarget: "umd-module", ES2015 module wrapped in UMD
libraryTarget: "commonjs-module", ES2015 module wrapped in CommonJS
libraryTarget: "commonjs2", exported with module.exports
libraryTarget: "commonjs", exported as properties to exports
libraryTarget: "amd", defined with AMD defined method
libraryTarget: "this", property set on this
libraryTarget: "var", variable defined in root scope
You can learn more about libraryTarget here
So finally you can access all you wanted from library MyLibrary.
<script>
window.addEventListener("load", () => {
const mySpaceShip = MyLibrary;
console.log(`Traveling to ${MyLibrary.target} with ${MyLibrary.crewmates} crewmates`)
}, false)
</script>

Related

digest-fetch and webpack - fetch is not a function

The Problem
TypeError: fetch is not a function
at DigestClient.fetch (webpack-internal:///./node_modules/digest-fetch/digest-fetch-src.js:48:24)
at User.create (webpack-internal:///./node_modules/mongodb-atlas-api-client/src/user.js:53:26)
at Function.createOrgDBUser (webpack-internal:///./src/OrgUtils.ts:87:51)
at Function.createOrg (webpack-internal:///./src/apis/OrgAPI.ts:373:39)
at processTicksAndRejections (internal/process/task_queues.js:97:5)
at async APIResponse.processHandlerFunction (webpack-internal:///./node_modules/apilove/lib/APIResponse.ts:27:31)
That's the error I'm getting trying to use mongodb-atlas-api-client#2.3.1 to create indexes on a collection. I'm seeing this error locally and in aws-lambda.
atlasClient.user.create({...})
I use webpack to bundle my api so I think the issue is in how I'm bundling but in my research I haven't been able to come up with a solution.
digest-fetch, used by mongodb-atlas-api-client, uses node-fetch in absence of the native fetch function. However, I believe my webpack configuration coupled with the way digest-fetch imports the library is what's causing the issue.
The following line of code is from node-modules/digest-fetch/digest-fetch-src.js:8
if (typeof(fetch) !== 'function' && canRequire) var fetch = require('node-fetch')
If I change that to the below, everything works fine. In other words, it's importing the module not the main exported fetch function from node-fetch.
if (typeof(fetch) !== 'function' && canRequire) var fetch = require('node-fetch').default
The node-fetch/package.json describes three entry points.
"main": "lib/index.js",
"browser": "./browser.js",
"module": "lib/index.mjs",
I think what's happening is my webpack configuration is telling webpack to use the .mjs module entry point to build its output from node-fetch, which does export default fetch;.
My webpack.config.js
const path = require('path')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const CopyPlugin = require('copy-webpack-plugin')
const NodemonPlugin = require('nodemon-webpack-plugin')
const ZipPlugin = require('zip-webpack-plugin')
module.exports = (env, argv) => {
const config = {
target: 'node',
watchOptions: {
ignored: ['node_modules', '*.js', '*.js.map', '*.d.ts'],
},
entry: './src/APIHandler.ts',
output: {
path: path.resolve(__dirname, 'dist'),
filename: `APIHandler.js`,
libraryTarget: 'commonjs',
},
optimization: {
minimize: false,
// minimizer: [new TerserPlugin({})],
},
resolve: {
extensions: ['.ts', '.json', '.mjs', '.js'],
},
module: {
rules: [
{
test: /\.tsx?$/,
use: {
loader: 'ts-loader',
options: {
transpileOnly: true,
allowTsInNodeModules: true,
},
},
},
],
},
plugins: [
new CleanWebpackPlugin(),
new CopyPlugin([
{ from: path.join(__dirname, 'src/certs'), to: path.resolve(__dirname, 'dist', 'certs') },
]),
new NodemonPlugin(),
],
}
// eslint-disable-next-line no-console
console.log({ mode: argv.mode })
if (argv.mode === 'development') {
config.devtool = 'eval-cheap-module-source-map'
}
if (argv.mode === 'production') {
config.plugins.push(
new ZipPlugin({
filename: 'handler',
})
)
}
return config
}
FWIW, here's the version of each library currently installed in my node_modules. I'm using node v12.22.7 locally.
"digest-fetch": "1.2.1",
"mongodb-atlas-api-client": "2.31.0",
"node-fetch": "2.6.7",
"webpack": "4.46.0"
The Question
What am I missing? What change do I need to make to my webpack.config.js to have the require properly resolve to the main module export from node-fetch?
NOTE: In my research I've found other people having this problem but no resolutions that have helped me.
The solution was pretty simple. I added mainFields to the webpack config's resolve property.
resolve: {
extensions: ['.ts', '.json', '.mjs', '.js'],
mainFields: ['main', 'module'],
}
This tells webpack to first use the main property of a module's package.json, then fallback to the module property if it's not found.
For more information, see webpack's documentation.

How to use babel with webpack for ie11 compatibility

It's the first time i use webpack with babel, my goal is to make my small template app compatible with ie11.
For some reason I ignore, my JS does not work at all in ie11 even though I did set it as a target in my config. To test it, I use a ie11 on the internet but I don't have access to the stack errors since I'm on MacOS.
What am I missing here?
Source code for more info : https://github.com/VelynnXV/Front-End-Workflow
website : https://nifty-noether-cafbd5.netlify.app/
app.js
import regeneratorRuntime from "regenerator-runtime";
async function app() {
console.log('App entry point')
const template = document.getElementById('app')
await new Promise(r => setTimeout(() => r(), 2500))
template.innerHTML = `
<div class="web-container">
<div id="">
Async / awat test
</div>
</div>
`
console.log('App finished')
};
app();
webpack.config.json
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
mode: 'development',
entry: ['core-js/stable', './src/app.js'],
output: {
path: path.resolve(__dirname, './dist'),
filename: 'app.js',
},
devServer: {
publicPath: "./src/",
contentBase: path.join(__dirname, 'dist'),
compress: true,
port: 9000,
},
plugins: [
new HtmlWebpackPlugin({ // will generate the html file WITH app.js
// see plugin here : https://webpack.js.org/plugins/html-webpack-plugin/
template: './src/index.html',
filename: './index.html'
})
],
module: {
rules: [ // set of rules letting webpack know how to handle .xyz files
{
test: /\.m?js$/, // source: https://webpack.js.org/loaders/babel-loader/
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
}
}
],
},
};
babel.config.js
// babel.config.js
module.exports = api => {
return {
plugins: [
"#babel/plugin-proposal-nullish-coalescing-operator",
"#babel/plugin-proposal-optional-chaining",
"#babel/plugin-transform-runtime",
],
presets: [
[
"#babel/preset-env",
{
useBuiltIns: "entry",
corejs:3,
// caller.target will be the same as the target option from webpack
targets: api.caller(caller => caller && caller.target === "node")
? { node: "current" }
: { chrome: "58", ie: "11" }
}
]
]
}
}
package.json
{
"name": "front-end-workflow",
"version": "1.0.0",
"description": "",
"main": "src/app.js",
"scripts": {
"dev": "npm run clean && npm run build && webpack serve",
"build": "webpack",
"clean": "rimraf ./dist"
},
"author": "",
"license": "ISC",
"devDependencies": {
"#babel/core": "^7.12.17",
"#babel/plugin-transform-runtime": "^7.12.17",
"#babel/preset-env": "^7.12.17",
"babel-loader": "^8.2.2",
"css-loader": "^5.0.2",
"html-loader": "^2.1.0",
"html-webpack-plugin": "^5.2.0",
"sass": "^1.32.8",
"sass-loader": "^11.0.1",
"style-loader": "^2.0.0",
"webpack": "^5.23.0",
"webpack-cli": "^4.5.0",
"webpack-dev-server": "^3.11.2"
},
"dependencies": {
"#babel/runtime": "^7.6.3",
"core-js": "^3.3.2"
}
}
You almost have a complete configuration for IE11 support. The only thing you're missing is a target: "es5" option in your webpack configuration. Babel correctly transpiled your files. Webpack also injected all the necessary polyfills. However, you need to tell Webpack when it bundles the code together to use a syntax that your target browser can understand. For whatever reason, Webpack set the default to a version of ES that contained arrow functions. The error that IE11 console was showing (SCRIPT1002:syntax error) was pointing at the very first occurrence of an arrow function in your bundled app.js file.
An extra tip: use comments: false in your babel config to strip the code comments out of your bundle. This can slightly decrease the size of your bundle.
You can git apply this diff in your repo to take the changes in.
diff --git a/babel.config.js b/babel.config.js
index 8d2442b..273176c 100644
--- a/babel.config.js
+++ b/babel.config.js
## -2,6 +2,7 ##
module.exports = api => {
return {
+ comments: false,
plugins: [
"#babel/plugin-transform-runtime",
],
diff --git a/webpack.config.js b/webpack.config.js
index 2243a11..08af521 100644
--- a/webpack.config.js
+++ b/webpack.config.js
## -21,6 +21,7 ## module.exports = {
filename: './index.html'
})
],
+ target: "es5",
module: {
rules: [ // set of rules letting webpack know how to handle .xyz files using loader
// see loaders : https://webpack.js.org/loaders/

Webpack renames functions

Hello i have some problems with webpack. I have this config for webpack
module.exports = {
name: "front",
mode: "production",
context: path.resolve(__dirname, 'src'),
entry: [
'./jquery/photoswipe.addon_offer_and_order.min.js',
'./jquery/photoswipe.min.js',
'./jquery/photoswipe-ui-default.min.js',
'./deprecated.js',
'./index.js',
],
output: {
filename: "index.min.js",
path: path.resolve(__dirname, 'dist')
},
optimization: {
moduleIds: 'named'
}
}
All good but i have a deprecated.js and have all deprecated functions in it...
Example:
function updateSearchCharacteristic(url, category_id) {
console.warn("This method is deprecated please use shopSearch.updateCharacteristic()");
return shopSearch.updateCharacteristic(url, category_id);
}
function moveBlockAnfrageGuest() {
console.warn("This method is deprecated please use shopUser.moveOrderAndOfferLinkForGuest()");
return shopUser.moveOrderAndOfferLinkForGuest();
}
Webpack rename all these functions, if someone used the old functions, he does not see errors and the return does not work ..
How not to rename functions in this file, but compress
I resolved this problem :
npm install -D script-loader terser-webpack-plugin
Added a module into config and 'require' a plugin
const TerserPlugin = require('terser-webpack-plugin')
module: {
rules: [
{
test: /deprecated.js/,
use : [
{
loader: 'script-loader',
options:{
plugins: [
new TerserPlugin({
terserOptions: {
keep_fnames: true,
}
})
]
}
}
]
}
]
}

How to include and use DefinePlugin in webpack config?

Hi there i am trying to use the define plugin so i can update the version number to make sure my JS refreshes after releasing a new build. I can't seem to get DefinePlugin to work properly though. I see it in the folder webpack and i'm trying to follow the documentation but i get errors that it isn't found. Here is my config:
const path = require('path'),
settings = require('./settings');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const webpack = require('webpack');
module.exports = {
entry: {
'scrollerbundled': [settings.themeLocation + "js/scroller.js"],
'mapbundled': [settings.themeLocation + "js/shopmap.js"],
'sculptor': [settings.themeLocation + "js/sculptor.js"]
},
output: {
path: path.resolve(__dirname, settings.themeLocation + "js-dist"),
filename: "[name].js"
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['#babel/preset-env']
}
}
}
],
plugins: [new webpack.DefinePlugin({
PRODUCTION: JSON.stringify(true),
VERSION: JSON.stringify('5fa3b9'),
})]
},
optimization: {
minimizer: [new UglifyJsPlugin({
uglifyOptions: {
mangle: true,
output: {
comments: false
}
}
})]
},
mode: 'production'
}
{
"parser": "babel-eslint",
"extends": [
"airbnb",
"plugin:react/recommended",
"prettier",
"prettier/react"
],
"plugins": ["react", "import", "prettier"],
"env": {
"browser": true
},
"settings": {
"import/resolver": {
"webpack": {
"config": "webpack.dev.js"
}
}
}
}
That's my eslintrc. This is for use absolute imports created in your webpack config with the modules alias. You need to install eslint-import-resolver-webpack
I Have "webpack": "^4.28.4" and define in webpack config
new webpack.DefinePlugin({
PRODUCTION: JSON.stringify(true),
});
if you console that variables, you don't find it. I use in conditional
if (PRODUCTION) {
//do stuff
}
Another case is to set globals variables in a object and share with webpack.
here is an example
new webpack.ProvidePlugin({
CONFIG: path.resolve(__dirname, './CONSTS.js')
}),
// the path is src/CONST.JS
In the eslintrc file you can add that variables to avoid import errors.
"settings": {
"import/resolver": {
"webpack": {
"config": "webpack.dev.js"
}
}
}
then in any file you can use import {value} from 'CONFIG'
If you are using laravel mix, you can place that new webpack.DefinePlugin code into the plugins array of your .webpackConfig block:
webpack.mix.js:
mix
.webpackConfig({
devtool: 'source-map',
resolve: {
alias: {
'sass': path.resolve('resources/sass'),
}
},
plugins: [
new webpack.ProvidePlugin({
'window.Quill': 'quill', // <--------------------- this right here
__VERSION__: JSON.stringify('12345')
})
]
})
.js('resources/js/app.js', 'public/js')
.sass('resources/sass/app.scss', 'public/css')
.copy([
'resources/fonts/*',
], 'public/fonts');
By extrapolation, that means you can also add this code to the similar block in your regular (not laravel mix) webpack config.
Install devtools globally
npm install -g #vue/devtools
... and try again.
If уоu have any issues try following the official instructions.

Eslint errorring importing jsx without extension

I am trying, in es6, to import jsx files without requiring the .jsx extension:
import LoginErrorDialog from './LoginErrorDialogView';
Not:
import LoginErrorDialog from './LoginErrorDialogView.jsx';
While I have got webpack to import in this fashion successfully:
export default {
entry: './src/ui/js/app.js',
output: {
publicPath: '/',
filename: 'bundle.js'
},
resolve: {
extensions: ['.js', '.jsx'],
Eslint (esw webpack.config.* ./ --color --ext .js --ext .jsx) is still errorring.
Unable to resolve path to module './LoginView' import/no-unresolved
Any ideas?
I had the same issue here, and I fixed adding extra configuration in my .eslintrc.
In the extends property add:
"plugin:import/react"
In the settings property add:
"import/resolver": {
"node": {
"extensions": [".js",".jsx"]
}
}
Your .eslintrc will look like:
{
"extends": [
...
"plugin:import/react",
...
],
...
"settings": {
"import/resolver": {
"node": {
"extensions": [".js",".jsx"]
}
}
},
...
}
Add to rule section, below rule
"import/extensions": [0, { "js": "always" }]

Categories