webpack module function not found - javascript

I have a simple project with a few html files in root folder and a few javascript modules in scripts directory.
I want to start using webpack now because I want minification and to start using environments. Everything was working before I started using webpack.
I read documentation for Webpack 5 but could not find anything that solves my problem. So I came up with this webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require("html-webpack-plugin")
module.exports = {
entry: {
lib: "./scripts/lib.js"
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js'
},
devServer: {
contentBase: "./dist",
inline: true, //Enable watch and live reload
host: "localhost",
port: 8080,
stats: "errors-only",
https: false
},
plugins: [
new HtmlWebpackPlugin({
filename: "index.html",
template: "index.html",
hash: true
})
],
module: {
rules: [
{
test: /\.html$/i,
loader: 'html-loader',
},
],
},
};
My index.html imports and uses module functions like this:
<script type="module">
import * as lib from "./scripts/lib.js";
window.lib = lib;
</script>
<body onload="lib.myFn()">
</body>
But after running this webpack (using webpack serve) I am getting "is not a function" or "module not found" errors.
How can I compile and run my existing project with webpack without making any changes in my directory structure and fix this error so I can start using functions in lib.js in my index.html? Thanks.

Related

webpack-dev-server refuses to hot-reload html file

When using webpack-dev-server, when I make changes to the javascript file the changes are immediately reflected on the webpage.
However, when I make a change to the HTML file, the website does not reflect them. In order to see the new html page, I must first run webpack --mode production, and then, if I re-run webpack-dev-server --hot --mode development, I can see the new HTML changes.
This is quite annoying and I'd like my html changes to be hot-reloaded just like the javascript code. Is there a trick I'm missing? I've spent all day googling and playing with options. The only thing that has helped is to add
devServer:
...
devMiddleware: {
writeToDisk: true
},
to my webpack.config.js as per this answer. However, this has the following problem: My output dist/ folder gets clogged with .js files with checksum names every time a hot reload happens, which is also really annoying.
My project tree:
The full webpack.config.js:
const HtmlWebpackPlugin = require("html-webpack-plugin");
const path = require('path');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
entry: './src/index.ts',
watch: true,
module: {
rules: [
{
test: /\.ts?$/,
use: 'ts-loader',
exclude: /node_modules/,
},
{
test: /\.css$/,
use: [
'style-loader',
'css-loader'
]
},
],
},
resolve: {
extensions: ['.tsx', '.ts', '.js'],
},
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
publicPath: '/dist/'
},
plugins: [
new HtmlWebpackPlugin({
title: "My app",
template: "./src/index.html",
/* This output directory is relative to the **OUTPUT** 'publicPath'!
So, if you were to write "./dist/index.html" below, it would output it in "./dist/dist/index.html"!
(You can verify this by running `npx webpack --watch` and looking what files it touches/generates.)
*/
filename: "index.html",
inject: "body"
})
],
devServer: {
// devMiddleware: { writeToDisk: true },
static: {
directory: path.join(__dirname, "dist"),
watch: true
},
compress: true,
webSocketServer: 'ws',
host: '0.0.0.0',
port: 10000,
/* Ensure I can access the server directly, without incurring the 'invalid host header' error */
allowedHosts: "all",
/* So that the webpack-dev-server reloads when I change the index.html file, even though it isn't explicitly listed anywhere. */
watchFiles: ['src/**/*'],
open: true,
hot: true,
},
};
Nevermind, I have found the issue:
Unfortunately Stackoverflow doesn't support line numbers, but if you look in the webpack.config.js code in my original question, you will find the following code:
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
publicPath: '/dist/'
},
That publicPath parameter appears to be what was causing the problem. Removing it made the hot-reload 'magic' autodetect that I've changed the HTML file, and re-deploy it.

Webpack 5 Module federation : Unable to Import the Remote app

I have a vanilla JS app and an Angular app. I am trying to link both these apps using module federation, both on my local environment. The following is webpack config file for vanilla js app which acts as remote
module.exports = {
entry: ['./src/index.js'],
output: {
publicPath: config.get('publicPath')
},
module: {
rules: [
{
test: /\.js$/,
exclude: /(node_modules)/,
use: ['babel-loader'],
}
]
},
plugins: [
new HTMLWebpackPlugin({
template: path.resolve(__dirname, 'demo/index.html')
}),
new ModuleFederationPlugin({
name: 'remote',
exposes: {
'./createWidget': './src/index.js'
}
}),
],
devServer: {
host: "localhost.remote.org",
port: 8080
}
};
I ran the webpack dev server, so hitting http://localhost.remote.org:8080/remote.js will give me the file. So this is the webpack of my Angular app which is consuming the remote app:
module.exports = {
devtool: 'source-map',
context: __dirname,
entry: {
polyfills: './src/polyfills.ts',
main: './src/main.ts'
},
...
...
plugins : [
new ModuleFederationPlugin({
name: "HostApp",
remotes: {
remote: "remote#http://localhost.finra.org:8080/remote.js",
}
}),
]
}
Note I am trying to import the dependency in my component.ts file as follows:
import * as Widget from 'remote/createWidget'
When I run ng serve, I get the "module not found" error. I'm not sure what exactly is going wrong. How can I fix this?
Error: src/app/component1/component1.component.ts:30:28 - error TS2307: Cannot find module 'remote/createWidget' or its corresponding type declarations.
30 import * as Widget from 'remote/createWidget'

webpack 5 does not accept any setting for devtool

When building with webpack 5, I get the error:
[webpack-cli] Invalid configuration object. Webpack has been initialized using a configuration object that does not match the API schema.
- configuration.devtool should match pattern "^(inline-|hidden-|eval-)?(nosources-)?(cheap-(module-)?)?source-map$".
BREAKING CHANGE since webpack 5: The devtool option is more strict.
Please strictly follow the order of the keywords in the pattern.
In my webpack.config.js however, I have the setting:
devtool: 'eval-cheap-source-map',
Ive also tried eval as value which also does not work, although this website (https://webpack.js.org/configuration/devtool/) seems to indicate that it should.
I do not understand, what is going wrong here?
edit:
my webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/app.js',
plugins: [
new HtmlWebpackPlugin({
title: 'MyApp',
}),
],
output: {
filename: 'main.js',
path: path.resolve(__dirname, 'dist'),
libraryTarget: 'var',
library: 'MyApp'
},
resolve:{
alias:{
EVENTS: path.resolve(__dirname, "src/events"),
MODELS: path.resolve(__dirname, "src/models"),
GUI: path.resolve(__dirname, "src/gui"),
HELPER: path.resolve(__dirname, "src/helper")
}
},
devtool: 'eval-cheap-source-map',
devServer: {
watchContentBase: true,
contentBase: path.resolve(__dirname, 'dist'),
port: 9000
},
module: {
rules: [
{
test:/\.css$/,
use:['style-loader', 'css-loader']
}
]
},
}
my buildscript is webpack src/app.js -d --watch
Remove the -d parameter from your build script. -d stands for devtool, but it is not followed by a parameter value in your command.

How to run unit test with webpack?

I have a Node Js server that I bundled with webpack with the following config:
module.exports = {
entry: './build/index.js',
output: {
filename: 'main.js',
path: path.resolve(__dirname, 'dist'),
devtoolModuleFilenameTemplate: '../[resource-path]',
},
target: 'node',
node: {
__dirname: true,
},
externals: {
kcors: 'kcors',
'koa-bodyparser': 'koa-bodyparser'
},
module: {
rules: [
{
test: /\.js$/,
use: ["source-map-loader"],
enforce: "pre"
},
],
},
resolve: {
extensions: ['.js'],
},
// plugins: [
// new webpack.DefinePlugin({
// "process.env": JSON.stringify(dotenv.parsed)
// }),
// ],
devtool: 'eval-source-map'
};
This created a single file main.js inside dist
Everything looks good so far. I manually tested the server and it works.
Now, before I used webpack, I have a set of unit tests that I named with the .spec.js suffix inside my entry folder (the build/ folder) and each .js file has each own .spec file sibling located in the same directory of the .js.
To run theses unit test, I used mocha with the command: mocha build/**/*.spec.js --recursive --timeout 20000
Since I am new to webpack and the concept of bundling, how do I run the same tests from the main.js file ? I want to make sure that all tests are still passing in the bundled file
use
npm install mocha mocha-loader
config your webpack.config.js file like:
module.exports = {
entry: './entry.js',
output: {
path: __dirname,
filename: 'bundle.js',
},
module: {
rules: [
{
test: /test\.js$/,
use: 'mocha-loader',
exclude: /node_modules/,
},
],
},
};
then, call your test file from your main file like:
(into app.js)
import test from 'allMyTests';

Webpack - browser refresh on a file change which isn't module

I want to refresh page when I change (save) ./src/*.js files in my code editor.
The problem is I'm not importing this files in my entry point (with import in index.js) but I'm joining them with a plugin so code is in browser's global scope rather then in module.
Basically I want to split longer JavaScript code into smaller files, I don't want to have modules.
I've tried many configurations and closest to my needs is that below, except that it doesn't refresh browser, (it recompiles).
How can I achieve recompile and refresh on JavaScript which should be in globalscope of the browser (or all code in one module)?
webpack.config.js:
const path = require('path');
const MergeIntoSingleFilePlugin = require('webpack-merge-and-include-globally');
const FileWatcherPlugin = require("file-watcher-webpack-plugin");
module.exports = {
context: __dirname,
entry: { bundle: './src/index.js' },
output: {
filename: '[name].js',
path: path.resolve(__dirname, 'dist')
},
module: {
rules: [{
test: /\.css$/,
use: [
'style-loader',
'css-loader'
]
}]
},
plugins: [
new MergeIntoSingleFilePlugin({
files: {
"app.js": [
path.resolve(__dirname, './src/setup.js'),
path.resolve(__dirname, './src/buttons.js'),
path.resolve(__dirname, './src/circle.js'),
path.resolve(__dirname, './src/wall.js')
]
}
}),
new FileWatcherPlugin({
root: __dirname,
files: ['*.js']
})
],
devServer: {
contentBase: './dist',
watchOptions: {
aggregateTimeout: 300,
poll: 1000
},
hot: true,
inline: true,
// publicPath: "./src",
watchOptions: {
ignored: './node_modules/'
}
}
};
npm start:
webpack-dev-server --open --inline --hot --watch --progress
and the setup.js, buttons.js etc are regular JS script files, not exported classes.
Any ideas appreciated!

Categories

Resources