webpack - cannot find module from dist bundle - javascript

So I'm trying to require dynamically from my node application a dist asset. And I'm getting the following error:
{"applicationLog":{"severity":"ERROR","timestamp":"2022-08-05T06:54:57.275Z","exception":{"type":"Error","message":"Cannot find module '/Users/lekoma/evelin/product-listing-fragment/dist/modern/fragment.js'","stack":"Error: Cannot find module '/Users/lekoma/evelin/product-listing-fragment/dist/modern/fragment.js'\n at webpackEmptyContext (webpack://product-listing-fragment/./node_modules/#jsmdg/react-fragment-scripts/server/_sync?:2:10)\n at getFragment (webpack://product-listing-fragment/./node_modules/#jsmdg/react-fragment-scripts/server/fragmentSsrRouter.js?:84:98)\n at createFragmentSsrRouter (webpack://product-listing-fragment/./node_modules/#jsmdg/react-fragment-scripts/server/fragmentSsrRouter.js?:121:20)\n at eval (webpack://product-listing-fragment/./node_modules/#jsmdg/react-fragment-scripts/server/createServer.js?:142:5)\n at Plugin.exec (/Users/lekoma/evelin/product-listing-fragment/node_modules/avvio/plugin.js:132:19)\n at Boot.loadPlugin (/Users/lekoma/evelin/product-listing-fragment/node_modules/avvio/plugin.js:274:10)\n at processTicksAndRejections (node:internal/process/task_queues:83:21)","code":"MODULE_NOT_FOUND"},"message":"Could not read fragment entry point"}}
The dist folder structure looks like following:
/dist/modern/fragment.js
The output of the node generated code is in a different folder:
build/server/index.js
Do you know who I could achieve to read dynamically from the dist folder?
source code node index.js
function getFragment(fragmentAssets) {
try {
const { Fragment } = require(path.join(
paths.clientOutputDirectory,
MODERN_BROWSER_STAGE || 'modern',
getFragmentEntryPointFromAssets(fragmentAssets), // the resolving path is correct, but the module could not be found/interpreted
));
return Fragment;
} catch (error) {
unpreparedLogger.withException(error).error('Could not read fragment entry point');
process.exit(1);
}
}
webpack config
module.exports = function webpackServerConfig() {
return {
target: 'node', // in order to ignore built-in modules like path, fs, etc.
mode: 'development',
externalsPresets: { node: true }, // in order to ignore built-in modules like path, fs, etc
externals: [
nodeExternals({
allowlist: [/#jsmdg\/react-fragment-scripts\/.*/, /#jsmdg\/yoshi\/.*/]
})], // in order to ignore all modules in node_modules folder
entry: {
server: {
import: paths.serverEntry,
filename: 'server/index.js',
},
shared: {
import: paths.sharedEntry,
filename: 'shared/index.js',
},
},
resolve: {
extensions: paths.moduleFileExtensions
.map(ext => `.${ext}`)
.filter(ext => useTypescript || !ext.includes('ts')),
},
output: {
path: paths.BFFOutputDirectory,
clean: true,
},
optimization: {
minimize: isEnvProduction,
minimizer: [new TerserPlugin()],
},
module: {
strictExportPresence: true,
rules: [
{
oneOf: [
{
test: /\.(js|jsx|ts|tsx)$/,
include: [
paths.clientSourceDirectory,
paths.sharedSourceDirectory,
paths.serverSourceDirectory,
/node_modules\/(#jsmdg\/react-fragment-scripts|#jsmdg\/yoshi)\/.*/,
],
exclude: [
isEnvProduction ? /__mock/ : undefined,
].filter(Boolean),
loader: require.resolve('babel-loader'),
options: {
babelrc: false,
configFile: false,
presets: [[require.resolve('../babel/server')]],
},
},
],
},
],
},
};
};

Related

Read the contents of the module file/stream into a BLOB

I create a BLOB file and write JavaScipt code there, then create a URL and import the module from it.
const myJSFile = new Blob( [ 'export default true;' ], { type: 'application/javascript' } );
const myJSURL = URL.createObjectURL( myJSFile );
import( myJSURL ).then(async ( module ) => {
console.log( module.default );
});
This works great in the browser console. However, I am having a problem when building a project using Webpack.
I suspect the problem is with WebPack or Babel configuration.
Webpack common config:
const path = require('path');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CopyWebpackPlugin = require("copy-webpack-plugin");
module.exports = {
// Where webpack looks to start building the bundle
entry: [
'core-js/modules/es6.promise',
'core-js/modules/es6.array.iterator',
'./src/main.js',
],
target: 'web',
// Where webpack outputs the assets and bundles
output: {
path: path.resolve(__dirname, 'dist'),
assetModuleFilename: '[name].[contenthash].[ext]',
filename: '[name].[contenthash].bundle.js',
chunkFilename: '[id].[chunkhash].bundle.js',
// publicPath: '/',
},
// Determine how modules within the project are treated
module: {
rules: [
{
test: /\.(gif|png|jpe?g)$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'assets/images/'
}
}
]
},
// JavaScript: Use Babel to transpile JavaScript files
{ test: /\.js$/, use: ['babel-loader'] },
// Images: Copy image files to build folder
{ test: /\.(?:ico|gif|png|jpg|jpeg)$/i, type: 'asset/resource' },
// Fonts and SVGs: Inline files
{ test: /\.(woff(2)?|eot|ttf|otf|svg|)$/, type: 'asset/inline' },
],
},
// Customize the webpack build process
plugins: [
// Generates an HTML file from a template
new HtmlWebpackPlugin({
// template: path.resolve(__dirname, 'src/index.html'), // шаблон
template: 'src/index.html',
// filename: 'index.html', // название выходного файла
// inject: false, // true, 'head'
minify: {
removeComments: true,
collapseWhitespace: true,
removeRedundantAttributes: true,
useShortDoctype: true,
removeEmptyAttributes: true,
removeStyleLinkTypeAttributes: true,
keepClosingSlash: true,
minifyJS: true,
minifyCSS: true,
minifyURLs: true
},
// chunks: 'all',
// excludeChunks: [],
}),
new CopyWebpackPlugin(
{
patterns: [
{ from: 'src/assets', to: 'assets' },
// { from: 'src/components', to: 'components' },
]
}
),
],
resolve: {
// modules: [path.resolve(__dirname, 'src'), 'node_modules'],
extensions: ['.js', '.jsx', '.json', '.ts'],
alias: {
'#': [
path.resolve(__dirname, 'src'),
'./src/main.js'
],
},
},
}
Babel config
module.exports = {
presets: [
[
'#babel/preset-env',
{
targets: {
esmodules: true,
},
},
],
],
plugins: [
'#babel/plugin-proposal-class-properties',
'#babel/plugin-transform-runtime',
"#babel/plugin-syntax-dynamic-import"
]
};
I've used require-from-string before, which internally uses the native Module module to achieve this.
Speaking generally, Blobs don't really interoperate well between browser and node land, and modules are also not treated identically.. so it's not a surprise that blob+module has problems. :)

mini-css-extract-plugin generates two additional JS files

I'm using the following webpack.config.js file to build two CSS files (editor.css and style.css) and a JS file (block.build.js) making use of the mini-css-extract-plugin plugin:
// Load webpack for use of certain webpack tools and methods
const webpack = require( 'webpack' );
// For extracting CSS (and SASS) into separate files
const MiniCssExtractPlugin = require( 'mini-css-extract-plugin' );
// Define JavaScript entry points
const entryPointNames = [ 'blocks', 'frontend' ];
// Setup externals
const externals = {};
// Setup external for each entry point
entryPointNames.forEach( entryPointName => {
externals[ '#/lg6' + entryPointName ] = {
this: [ 'lg6', entryPointName ]
}
} );
// Define WordPress dependencies
const wpDependencies = [ 'components', 'element', 'blocks', 'utils', 'date' ];
// Setup externals for all WordPress dependencies
wpDependencies.forEach( wpDependency => {
externals[ '#wordpress/' + wpDependency ] = {
this: [ 'wp', wpDependency ]
};
});
// Start of main webpack config
const config = {
// Set mode
mode: process.env.NODE_ENV === 'production' ? 'production' : 'development',
// Go through each entry point and prepare for use with externals
entry: {
index: './index.js',
style: './style.scss',
editor: './editor.scss',
},
// Include externals
externals,
// Set output
output: {
// Place all bundles JS in current directory
filename: 'block.build.js',
path: __dirname,
library: [ 'pluginnamespace', '[name]' ],
libraryTarget: 'this'
},
// Fall back to node_modules for file resolution
resolve: {
modules: [ __dirname, 'node_modules' ]
},
optimization: {
splitChunks: {
cacheGroups: {
editor: {
name: 'editor',
test: /editor\.(sc|sa|c)ss$/,
chunks: 'all',
enforce: true,
},
style: {
name: 'style',
test: /style\.(sc|sa|c)ss$/,
chunks: 'all',
enforce: true,
},
default: false,
},
},
},
module: {
rules: [
{
// Run JavaScript files through Babel
test: /\.js$/,
exclude: /node_modules/,
use: 'babel-loader',
},
{
// Setup SASS (and CSS) to be extracted
test: /\.(sc|sa|c)ss$/,
exclude: /node_modules/,
use: [
{
loader: MiniCssExtractPlugin.loader,
},
{
loader: 'css-loader',
options: {
sourceMap: process.env.NODE_ENV !== 'production',
},
},
{
loader: 'postcss-loader',
options: {
plugins: [ require( 'autoprefixer' ) ]
}
},
{
loader: 'sass-loader',
options: {
sourceMap: process.env.NODE_ENV !== 'production',
},
},
],
},
]
},
plugins: [
// Setup environment conditions
new webpack.DefinePlugin( {
'process.env.NODE_ENV': JSON.stringify(
process.env.NODE_ENV || 'development'
)
} ),
new MiniCssExtractPlugin( {
filename: './css/[name].css',
} ),
// For migrations from webpack 1 to webpack 2+
new webpack.LoaderOptionsPlugin( {
minimize: process.env.NODE_ENV === 'production',
debug: process.env.NODE_ENV !== 'production',
} )
],
// Do not include information about children in stats
stats: {
children: false
}
};
module.exports = config;
Everything is working as expected but, for some reason, in addition to the block.build.js file, I'm getting two more JS files named 0.block.build.js and 2.block.build.js with the following content:
(window.webpackJsonp=window.webpackJsonp||[]).push([[0],[,function(n,w,o){}]]);
My question is, why are these two additional files are being created and how can I avoid this?
Thanks in advance
You should remove these 2 line
style: './style.scss',
editor: './editor.scss',
Also you can import those 2 scss file in your index.js
import "style.scss";
import "editor.scss";
And mini-css-extract-plugin will take care the rest for you
As an alternative, if you don't want to import the scss files in your js files, I found you can use a webpack plugin such as Ignore Emit Webpack in your webpack.config.js file to prevent the creation of the extra js files:
const IgnoreEmitPlugin = require('ignore-emit-webpack-plugin');
module.exports = {
// ...
plugins: [
new IgnoreEmitPlugin(['0.block.build.js', '2.block.build.js'])
]
// ...
};

When typing command "npm run dev" for webpack, it creates a folder that ends with NaN

i'm taking a course in Lynda.com "learning-full-stack-javascript-development-mongodb-node-and-react" and when i use the command "npm run dev" to create a bundle.js file in "public" folder, it creates a folder "publicNaN" and puts the file bundle.js in it.
i want it to be in the "public" folder.
here is the webpack.config.js file:
const path = require("path");
const BUILD_PATH = path.join(__dirname, "./public");
// See https://github.com/Microsoft/vscode/blob/master/extensions/shared.webpack.config.js
module.exports = {
mode: "production",
target: "node",
node: {
__dirname: false
},
entry: {
extension: ["./src/index.js"]
},
output: {
path: BUILD_PATH + + '/public',
filename: "bundle.js",
libraryTarget: "commonjs",
},
resolve: {
extensions: [".ts", ".js"]
},
externals: {
"vscode": "commonjs vscode"
},
module: {
rules: [
{
test: /\.ts$/,
use: [
{
loader: "ts-loader"
}
],
exclude: /node_modules/
},
{
test: /\.mjs$/,
type: "javascript/auto",
use: []
}
]
},
stats: {
children: false,
modules: false
}
};
You're already setting your BUILD_PATH to /public here:
const BUILD_PATH = path.join(__dirname, "./public");
So there's no need to add it in the output object. Also the two + signs tries to convert to a number. That's why you get NaN at the end.
So change the output object to this:
output: {
path: BUILD_PATH,
filename: "bundle.js",
libraryTarget: "commonjs",
},

Exclude unused dynamic modules from bundle using react-loadable

I've got an issue with react-loadable where I've got a large list of components that may or may not be rendered depending on user-generated content. I'm using a switch statement to render the correct ones.
A (simplified) list of user-generated content might look like this:
const content = ['Paragraph', 'Image', 'Paragraph', 'Canvas'];
Now, what I want to do is have ONLY the components that are used enter the bundle. Instead, ALL of them that get included in the following switch case are in the bundle. Why?
const collection = (name) => {
switch(name) {
case 'Paragraph':
return Loadable({
loader: () => import('dynamic-paragraph-component'),
loading(){ return null }
})
case 'Video':
return Loadable({
loader: () => import('dynamic-video-component'),
loading() { return null }
})
// etc
}
}
For example, dynamic-video-component ends up in the bundle even if it's not used. Is there a way to prevent this?
Current webpack setup with Webpack 4
//----------------------------------
//
// Bundler
//
//----------------------------------
import webpack from 'webpack';
import path from 'path';
import { ReactLoadablePlugin } from 'react-loadable/webpack';
module.exports = (files) => {
console.log(files);
return {
mode: 'production',
entry: './src/client/index.js',
output: {
filename: './main.pkgd.js',
chunkFilename: './[name].pkgd.js',
path: path.resolve(__dirname, 'tmp'),
publicPath: '/',
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
options: {
babelrc: false,
presets: [
[
'env',
{
modules: false,
targets: {
browsers: ['last 2 versions'],
},
},
],
'flow',
'react',
],
plugins: [
'transform-class-properties',
'syntax-dynamic-import',
'react-loadable/babel',
],
},
},
],
},
optimization: {
splitChunks: {
cacheGroups: {
default: false,
vendors: false,
// vendor chunk
vendor: {
name: 'vendor',
chunks: 'all',
test: /node_modules/,
priority: 20,
reuseExistingChunk: true,
enforce: true,
},
common: {
name: 'main',
minChunks: 1,
chunks: 'initial',
priority: 10,
reuseExistingChunk: true,
enforce: true,
},
},
},
},
plugins: [
new webpack.DefinePlugin({
__isBrowser__: 'true',
env: {
NODE_ENV: JSON.stringify('production'),
},
}),
new ReactLoadablePlugin({
filename: './tmp/react-loadable.json',
}),
],
};
};
The way you have it set up looks correct, so I'd wager the problem is in your webpack.config.js file.
Assuming you are using Webpack 4, you need to reference the code-splitting docs.
Specifically, make sure you have configured the chunkFilename option. Also, you can add comment directives like /* webpackChunkName: "dynamic-video-component" */ for easier debugging.

Webpack Dev Server Not Hot Reloading .vue files

Been working on a project and was sure HMR was working, any of my .js files if I would update them webpack would compile and the module would be replaced all hot like.
I was working on a .vue file and webpack would recompile, but there was no super fresh HMR.
Hoping someone can take a look and tell me if something is off:
The script I'm using in the cli looks like this.
webpack-dev-server --d --watch --output-path ./public --config ./_src/webpack.config.js --progress --env.dev
I'm guessing the most important bit to look at is this:
devServer: {
contentBase: 'public',
hot: true,
filename: 'main.js',
overlay: true,
stats: { colors: true },
port: 3000,
proxy: {
'/': {
target: 'http://moment.local/',
secure: false,
changeOrigin: true
}
},
historyApiFallback: true
},
But here is my whole config if it helps.
const webpack = require('webpack')
const {resolve} = require('path')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
module.exports = env => {
const addPlugin = (add, plugin) => add ? plugin : undefined
const ifProd = plugin => addPlugin(env.prod, plugin)
const removeEmpty = array => array.filter(i => !!i)
// Our Sass Extraction Plugin
const extractSass = new ExtractTextPlugin({
filename: 'style.css',
disable: env.dev
})
return {
entry: {
'vendor': ['jquery', 'KlaviyoSubscribe', 'learnq', 'select2', 'slick-carousel', 'moment', 'lodash'],
'main': resolve(__dirname, './js/index.js')
},
output: {
filename: '[name].js',
path: resolve(__dirname, '../public/'),
pathinfo: !env.prod
},
module: {
loaders: [
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
loaders: {
css: 'vue-style-loader!css-loader!postcss-loader!sass-loader', // <style lang='scss'>
scss: 'vue-style-loader!css-loader!postcss-loader!sass-loader', // <style lang='scss'>
sass: 'vue-style-loader!css-loader!postcss-loader!sass-loader?indentedSyntax' // <style lang='sass'>
}
}
},
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader'
},
{ test: /\.s(c|a)ss$/,
use: extractSass.extract({
fallback: 'style-loader',
use: [
{
loader: 'css-loader',
options: {
importLoaders: 1,
sourceMap: true
}
},
'postcss-loader?sourceMap',
'sass-loader?sourceMap'
]
})
},
{
test: /\.(png|jpg|gif|svg)$/,
loader: 'file-loader',
options: {
name: '[name].[ext]?[hash]'
}
}
]
},
devtool: env.prod ? 'source-map' : 'eval',
devServer: {
contentBase: 'public',
hot: true,
filename: 'main.js',
overlay: true,
stats: { colors: true },
port: 3000,
proxy: {
'/': {
target: 'http://moment.local/',
secure: false,
changeOrigin: true
}
},
historyApiFallback: true
},
bail: env.prod, // Fail out on the first error if production
resolve: {
alias: {
'vue$': 'vue/dist/vue.common.js'
}
},
plugins: removeEmpty([
extractSass,
new webpack.HotModuleReplacementPlugin(),
new webpack.optimize.CommonsChunkPlugin({
// Let's create js for our vendor scripts
name: 'vendor',
// (with more entries, this ensures that no other module
// goes into the vendor chunk)
minChunks: Infinity
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'commons',
filename: 'commons.js',
// (Modules must be shared between 2 entries)
minChunks: 2
})
...
])
}
}
Really struggling here so anything would be great.
It sounds like you want the "hot" behaviour but you are missing the --hot option in the script you posted. The documentation for that option is here.
You have a lot of options already; just add --hot and that should do the trick.
UPDATE:
I do see that you have the hot: true set in the devServer property of your webpack config, but if I don't use --hot in the cli, I get the following error in the console, so that is why I am saying to use it even though you would think it would be covered by the config - its not.
Uncaught Error: [HMR] Hot Module Replacement is disabled.
Add a file called vue.config.js in your root directory.
Inside it you can enable hot reloading via:
module.exports = {
devServer: {
watchOptions: {
poll: true
}
}
};
I used this settings in a project that was set up via vue create.

Categories

Resources