How to include readline in webpack - node.js

I have created nodejs console app and trying to minify it with webpack.
webpack.config.js I got:
const path = require('path');
module.exports = {
externals: {
fs: "require('fs')",
readline: "require('readline')",
},
entry: './index.js',
output: {
path: path.resolve(__dirname, 'bin'),
filename: 'bin.js'
},
mode: 'development'
};
Everything goes ok before I run builded app:
readline.js:189
input.on('data', ondata);
^
TypeError: input.on is not a function
at new Interface (readline.js:189:11)
at Object.createInterface (readline.js:69:10)
What should I do to prevent this error?

Somewhere I found the solution. In the webpack configuration file I must set target: node to point the collector what to do with standard external packages (e.g. readline, fs, path, etc.).

Related

Webpack when using readdirSync for require a library

I have a legacy code for my express app that read all routes files in specific dir and require them in a loop. Notice this code cant be changed:
app.js
const normalizedRoutes = fs.readdirSync(__dirname + '/src/routes/')
.map(routeFile => `/src/routes/${routeFile}`);
normalizedRoutes.forEach((normalizedRouteDir: string) => {
require(normalizedRouteDir)(app);
})
Now, I want to combine a Server Side Rendered application with the code above, using some JSX in routes files.
My problem is because the routes files are loaded on run time webpack not recognize them when creating the bundle.js file.
Therefore there are not routes files in the /src/routes/${routeFile} and when I run the bundle.js file I get an error message of:
Error: ENOENT: no such file or directory, scandir '/Users/******/build/src/routes/'
(the stars are for hiding full path)
webpack configs:
webpack.base.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
plugins: [new MiniCssExtractPlugin()],
module: { //remain
rules: [
{
test: /\.(ts|js)x?$/,
loader:'babel-loader',
exclude: /node_modules/,
options:{
presets:[
'#babel/react',
['#babel/env',{targets:{browsers:['last 2 versions']}}]
]
}
},
{
test: /\.css$/i,
use: [MiniCssExtractPlugin.loader, "css-loader"],
},
],
}
};
webpack.server.js
const path = require('path')
const {merge} = require('webpack-merge')
const baseConfig = require('./webpack.base.js');
const webpackNodeexternals = require('webpack-node-externals');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const config = {
mode: "development",
entry: {
main:"./app.ts",
},
resolve: {
extensions: [".js", ".jsx", ".json", ".ts"],
},
node: {
__dirname: true
},
output: {
libraryTarget: "commonjs",
path: path.join(__dirname, "build"),
filename: "bundle.js",
},
target: "node",
//Avoid put node modules of server when sending to browser
externals: [webpackNodeexternals()]
}
module.exports = merge(baseConfig,config)
scripts from package.json:
"dev:server": "nodemon --watch build --exec \"node build/bundle.js\" ",
"dev:build-server": "webpack --config webpack.server.js --watch",
When I copy the route files (js files) to the build directory it works of course but that means I don't run webpack on these files and therefore I can't include JSX\es6 features inside these files.
So my question is:
Is there any possible way to make these requires identify by webpack/babel to add them to bundle.js and avoid the need for seperate files (bundle.js and routes files)
If we cant do it, how can I run webpack on a folder seperatly from the bundle.js output and create a route folder in the correct path but after processed by babel?
Thanks!
Instead of using a Webpack you can try using a programmatic interface of babel, and transpile the files before requiring them.
Here is the link https://babeljs.io/docs/en/babel-core

NodeJS application cannot find modules after being bundled by Webpack

I'm creating a node/express server that I'm trying to bundle so that I can deploy it onto an IIS server. I should note that this is a backend server only. Once I try to run the code after it has been bundled, I get the following error:
ReferenceError: __WEBPACK_EXTERNAL_MODULE_dotenv__ is not defined
at eval (webpack:///external_%22dotenv%22?:1:18)
at Object.dotenv (C:\inetpub\wwwroot\my-deployments\server\bundle.js:271:1)
at __webpack_require__ (C:\inetpub\wwwroot\my-deployments\server\bundle.js:20:30)
at eval (webpack:///./src/server/server.js?:4:1)
at Object../src/server/server.js (C:\inetpub\wwwroot\my-deployments\server\bundle.js:169:1)
at __webpack_require__ (C:\inetpub\wwwroot\my-deployments\server\bundle.js:20:30)
at eval (webpack:///multi_./src/server/server.js?:1:18)
at Object.0 (C:\inetpub\wwwroot\my-deployments\server\bundle.js:216:1)
at __webpack_require__ (C:\inetpub\wwwroot\my-deployments\server\bundle.js:20:30)
at C:\inetpub\wwwroot\my-deployments\server\bundle.js:84:18
I understand that there seems to be an error with the dotenv module, however I tried with a basic app that only had express installed, and I got the same error but with express instead of dotenv. I figure this is an issue with my webpack.config.js but I can't seem to figure out what would be causing this problem.
webpack.config.js
const path = require('path')
const webpack = require('webpack')
const nodeExternals = require('webpack-node-externals')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
module.exports = {
target: 'node',
mode: 'development',
entry: {
bundle: ["./src/server/server.js"]
},
externals: [nodeExternals({
importType: 'umd'
})],
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
title: 'server'
})
],
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
}
}
The issue is in your nodeExternals options. Remove importType: 'umd' and re-bundle. I tested this locally with a small express app and your exact config and it worked for me.
The issue here is that you're telling webpack that all your imports are "external" (not bundled) and that they use umd (Universal Module Definition) to expose their contents.
Umd is often used for client side code so it'll run in multiple different environments (<script> tags, commonjs, amd, es6 modules and so on). As for server side / Nodejs only modules... not so much. The default value of importType is commonjs, which is Node's native module loading system and what the vast majority of server side packages will be using.

How to use webpack for pack node program

Can you provide me an example how to use webpack for pack node js project to single file with dependencies?
I wrote webpack config, but its not working, because is packed only first (index.js) file. Whats is wrong with my script?
var webpack = require('webpack');
var path = require('path');
var fs = require('fs');
var nodeModules = {};
fs.readdirSync('node_modules')
.filter(function (x) {
return ['.bin'].indexOf(x) === -1;
})
.forEach(function (mod) {
nodeModules[mod] = 'commonjs ' + mod;
});
module.exports = {
entry: './src/index.js',
target: 'node',
output: {
path: path.join(__dirname, 'build'),
filename: 'backend.js'
},
externals: nodeModules,
plugins: [
],
devtool: 'sourcemap'
}
src/index.js
src/library.js
src/library2.js
How to pack into single file with dependency from node_modules?
You should install webpack.
This is install command:
npm install --save-dev webpack#2.3.3 --cache /tmp/empty-cache --global
2.3.3 is version of your project.
You can specify version and then use this command:
webpack -w
It will work.

Using Firebase in Node Server Typescript File

• I recently implemented server side rendering using Angular Universal in my application.
• This required converting my node server file from .js to .ts.
• Typescript is compiled to javascript using webpack
• Everything works when I run the server using : ts-node server.ts
• After compiling to javascript using webpack, I get the following error for Firebase API's used in my server:
ERROR in ./node_modules/google-auto-auth/node_modules/mime/index.js
Module not found: Error: Can't resolve './types/standard' in '/Users/XX/Desktop/XX/XX/node_modules/google-auto-auth/node_modules/mime'
ERROR in ./node_modules/#google-cloud/storage/node_modules/mime/index.js
Module not found: Error: Can't resolve './types/standard' in '/Users/XX/Desktop/XX/OM-XX/node_modules/#google-cloud/storage/node_modules/mime'
etc. etc.
How can this be tackled?
My webpack config code:
const path = require('path');
const webpack = require('webpack');
module.exports = {
entry: {server: './server.ts'},
resolve: {extensions: ['.js', '.ts']},
target: 'node',
mode: 'none',
// this makes sure we include node_modules and other 3rd party libraries
externals: [/(node_modules|main\..*\.js)/],
output: {
path: __dirname,
filename: '[name].js'
},
module: {
rules: [
{test: /\.ts$/, loader: 'ts-loader'}
]
},
plugins: [
// Temporary Fix for issue: https://github.com/angular/angular/issues/11580
// for "WARNING Critical dependency: the request of a dependency is an expression"
new webpack.ContextReplacementPlugin(
/(.+)?angular(\\|\/)core(.+)?/,
path.join(__dirname, 'src'), // location of your src
{} // a map of your routes
),
new webpack.ContextReplacementPlugin(
/(.+)?express(\\|\/)(.+)?/,
path.join(__dirname, 'src'),
{}
)
]
}
Thank you!
Maybe this can be related to missing types?
Try to install missing typesfor all the packages that throw error
e.g: npm install --save #types/google-cloud__storage

webpack-dev-middleware and Express - can't get them to collaborate

I am trying to set up my first project using Webpack and Express but somehow I am doing something wrong.
This is what I did:
1. CREATED SAMPLE PROJECT
Created a sample project using express-generator. My folder structure is something like:
express-project
-app.js
-webpack.config.js
-public
-javascripts
-modules
-build
2. SET UP HANDLEBARS
Set up handlebars as view/template engine and created a couple of routes
3. WEBPACK CODE
Created the Webpack specific code/configuration as follows
webpack.config.js
var webpack = require('webpack');
var path = require('path');
var webpackHotMiddleware = 'webpack-hot-middleware/client?path=/__webpack_hmr&timeout=2000&overlay=false';
module.exports = {
resolve: {
alias: {
handlebars: path.resolve('public/vendor/handlebars-v4.0.5.js'),
bootstrap: path.resolve('public/vendor/bootstrap/js/bootstrap.js'),
pubsub: path.resolve('public/vendor/ba-tiny-pubsub.js')
}
},
context: path.resolve('public/javascripts'),
entry: {
cart: ['./modules/cart', webpackHotMiddleware],
index: ['./modules/products.js', webpackHotMiddleware],
vendor: ['bootstrap', 'pubsub', webpackHotMiddleware]
},
output: {
path: path.resolve('public/javascripts/build'),
publicPath: 'javascripts/build/',
filename: '[name].js',
chunkFilename: "[id].js"
},
module: {
loaders: [
// some loaders here
]
},
plugins: [
new webpack.optimize.OccurenceOrderPlugin(),
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin()
]
}
app.js
// some code before
var app = express();
(function() {
// Step 1: Create & configure a webpack compiler
var webpack = require('webpack');
var webpackConfig = require(process.env.WEBPACK_CONFIG ? process.env.WEBPACK_CONFIG : './webpack.config');
var compiler = webpack(webpackConfig);
// Step 2: Attach the dev middleware to the compiler & the server
app.use(require("webpack-dev-middleware")(compiler, {
noInfo: false,
publicPath: webpackConfig.output.publicPath,
stats: {
colors: true
}
}));
// Step 3: Attach the hot middleware to the compiler & the server
app.use(require("webpack-hot-middleware")(compiler, {
log: console.log,
path: '/__webpack_hmr',
heartbeat: 10 * 1000
}));
})();
// some code after
4. JS CODE ON TEMPLATE
Then on the handlebars page I require the bundled javascripts
<script src="javascripts/build/common.js"></script>
<script src="javascripts/build/vendor.js"></script>
<script src="javascripts/build/cart.js"></script>
5. NPM START
Finally if I start the server using the standard npm start I see in the shell that webpack bundles everything with no errors but if I go to localhost:3000/ it does not find any of the assets created by Webpack. Instead if I run webpack to create the various bundles as if I were on production, everything is created correctly and it works as expected.
Hope someone can figure out what I am doing wrong.
Thanks
I managed to figure out what was causing the problem, by adding a slash in these 2 lines everything started to work properly:
context: path.resolve('public/javascripts/'),
path: path.resolve('public/javascripts/build/'),

Resources