Cannot load Node native addons with webpack - node.js

Although I am using vue-cli in the example code to generate a webpack config, nothing is specific to vue.
I create the example app like this:
vue init webpack webpack_modules_example
Generated webpack.base.conf:
'use strict'
const path = require('path')
const utils = require('./utils')
const config = require('../config')
const vueLoaderConfig = require('./vue-loader.conf')
function resolve (dir) {
return path.join(__dirname, '..', dir)
}
module.exports = {
context: path.resolve(__dirname, '../'),
entry: {
app: './src/main.js'
},
output: {
path: config.build.assetsRoot,
filename: '[name].js',
publicPath: process.env.NODE_ENV === 'production'
? config.build.assetsPublicPath
: config.dev.assetsPublicPath
},
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'vue$': 'vue/dist/vue.esm.js',
'ad-block': 'ad-block/build/Release/ad-block.node',
'#': resolve('src'),
}
},
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
options: vueLoaderConfig
},
{
test: /\.js$/,
loader: 'babel-loader',
include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('img/[name].[hash:7].[ext]')
}
},
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('media/[name].[hash:7].[ext]')
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
}
},
]
},
node: {
setImmediate: false,
dgram: 'empty',
fs: 'empty',
net: 'empty',
tls: 'empty',
child_process: 'empty'
}
}
I want to include this library, so I do this:
npm install --save ad-block
And on the code (App.vue) I add this:
<script>
...
const {AdBlockClient, FilterOptions} = require('ad-block')
...
Because it's a native module, I need to install some loader for webpack (tried several):
npm install native-ext-loader --save-dev
Add the loader to the webpack config:
{
test: /\.node$/,
loader: "native-ext-loader"
},
And create an alias in the webpack config too:
alias: {
...
'ad-block': 'ad-block/build/Release/ad-block.node',
...
}
But when I run npm run dev and go to http://localhost:8080/
I see this error in the console:
Uncaught Error: Cannot open /ad-block.node: TypeError: Cannot read property 'dlopen' of undefined
at Object.eval (ad-block.node?9538:1)
at eval (ad-block.node:2)
at Object../node_modules/ad-block/build/Release/ad-block.node (app.js:733)
at webpack_require (app.js:679)
at fn (app.js:89)
at eval (App.vue?26cd:9)
at Object../node_modules/babel-loader/lib/index.js!./node_modules/vue-loader/lib/selector.js?type=script&index=0!./src/App.vue (app.js:757)
at webpack_require (app.js:679)
at fn (app.js:89)
at eval (App.vue?a8e9:1)
If I use this without webpack, it works. Not sure what am I missing!

NodeJS is a server-side programming environment and as such, supports “native” add-on modules compiled to run on the same host that runs your Node service.
While Node is programmed using JavaScript, it is not browser JavaScript and so native ad-ons cannot be expected to run in the browser.
See Node C++ Addons for more information.

Related

Problem with building react ssr server with express and webpack

I'm struggling with webpack setup for my ssr react server. I've read several posts here on stackoverflow, other articles and nothing works. Issue is connected with webpack-node-externals package. I've tried several configurations:
without nodeExternals: my app throws an error "process.hrtime" is not a function
with nodeExternals: my bundle is missing dependencies listed in mypackage.json (compression, etc.). This is because it leaves require('moduleName') everyywhere, obvious
with nodeExternals and with options.modulesFromFile argument set to
modulesFromFile: {
fileName: path.resolve(__dirname),
includeInBundle: ['dependencies']
}
I ended up here with error from user-agent module (not listed in my deps) "Cannot find module request". When I installed request manually, there where other errors I don't remember now.
Finally I don't know what I'm doing wrong. Here sample of my webpack config file:
const path = require('path');
const {
CleanWebpackPlugin
} = require('clean-webpack-plugin');
const NodePolyfillPlugin = require('node-polyfill-webpack-plugin');
const nodeExternals = require('webpack-node-externals');
const {
BundleAnalyzerPlugin
} = require('webpack-bundle-analyzer');
const IS_PRODUCTION = process.env.MODE === 'production';
const config = {
entry: path.resolve(__dirname, 'src/server/index.ts'),
mode: IS_PRODUCTION ? 'production' : 'development',
output: {
path: path.resolve(__dirname, 'dist/server'),
publicPath: IS_PRODUCTION ? 'dist/' : undefined,
filename: 'index.js',
},
externals: [nodeExternals()],
resolve: {
extensions: ['.js', '.ts', '.tsx', '.json'],
fallback: {
fs: false,
yamlparser: false,
tls: false,
net: false,
},
},
target: 'node',
module: {
rules: [{
test: /\.((t|j)s(x?))$/u,
exclude: /node_modules/,
use: {
loader: 'swc-loader',
},
},
{
test: /\.(ts|tsx)$/u,
exclude: /node_modules/,
loader: 'ts-loader',
options: {
configFile: path.resolve(__dirname, 'tsconfig.webpack.json'),
},
},
{
test: /\.(png|jpg|jpeg|ico)$/u,
exclude: /node_modules/,
loader: 'file-loader',
},
],
},
plugins: [new NodePolyfillPlugin(), new CleanWebpackPlugin()],
};
if (IS_PRODUCTION) {
config.optimization = {
minimize: true,
};
}
if (process.env.BUNDLE_ANALYZER === 'true') {
config.plugins.push(
new BundleAnalyzerPlugin({
analyzerMode: 'static',
reportFilename: 'bundle-report-server.html',
})
);
}
module.exports = config;
I've already managed to fix it on myself.
The problem was in node polyfill plugin which was not necessary in my webpack config and it was causing errors like process.hrtime is not a function

Webpack Babel build fails when importing files outside entry path

I have this project that i'm already using webpack + babel to build. I've hit a wall since what i want to do is share some constants between my node (server) and my react app (front-end).
My project structure is this
- app
- internals
- webpack
- different webpack configs (node, react-dev, react-production etc)
- server
- shared
- .babelrc
I've put some "constants" files into the shared folder that I use both from my app and from my server.
When I try to build my server I get this
ERROR in ./shared/reports.constants.js
Module build failed (from ./node_modules/babel-loader/lib/index.js):
TypeError: Cannot read property 'code' of null
at transpile (C:\Users\XXX\Desktop\XXX\XXX\node_modules\babel-loader\lib\index.js:70:21)
at Object.module.exports (C:\Users\XXX\Desktop\XXX\XXX\node_modules\babel-loader\lib\index.js
:173:20)
Below is my webpack config file. Any ideas what might be wrong ?
{
mode: 'production',
target: 'node',
externals: nodeExternals(),
entry: {
server: [path.join(process.cwd(), 'server/index.js')],
},
output: {
filename: '[name].js',
path: path.resolve(process.cwd(), 'build'),
// sourceMapFilename: '[name].js.map',
},
devtool: 'hidden-source-map',
module: {
rules: [
{
test: /\.css$/,
use: ExtractTextPlugin.extract(
{ fallback: 'style-loader', use: { loader: 'css-loader', options: { minimize: true } } }),
},
{ test: /\.jpg$/, use: [{ loader: 'file-loader', options: { name: '/images/[name].[ext]' } }] },
{ test: /\.md$/, use: [{ loader: 'markdown-with-front-matter-loader' }] },
{
test: /\.js$/,
exclude: [/node_modules/],
include: [/server/, /shared/],
use: [
'babel-loader',
{
loader: 'webpack-preprocessor-loader',
options: {
debug: process.env.NODE_ENV !== 'production',
directives: {
secret: false,
},
params: {
ENV: process.env.NODE_ENV,
DEBUG: process.env.NODE_ENV !== 'production',
PRODUCTION: process.env.NODE_ENV === 'production',
ENVIRONMENT: process.env.ENVIRONMENT,
},
verbose: false,
},
},
],
},
],
},
plugins
etc
}
.babelrc file
{
"presets": [
"#babel/preset-env"
],
"plugins": [
"react-hot-loader/babel",
"#babel/transform-runtime",
"transform-html-import-to-string"
]
}
I've added the /shared/ to the includes rules.
Thank you in advance
For some reason I already had a babel.config.js + the babelrc. All I had to do was go into the babel.config.js and add the shared folder to be included in the env => production.
Thank you for your time

Why can't I resolve nodejs default modules when using preset-env node?

I am writing a plugin for an app that runs Chromium Embedded Framework (CEF) with an older version of Node.
I threw webpack & babel into the app. When I run webpack, it fails on a file that has const fs = require('fs');, or any other default node package. This is happening both for my code and dependencies:
Module not found: Error: Can't resolve 'fs' in '/Users/me/repositories/myrepo/node_modules/chokidar'
My .babelrc is the following:
{
"presets": [
[
"#babel/preset-env",
{
"targets": {
"node": true
}
}
]
]
}
My webpack config is essentially:
module.exports = {
entry: './src/main.jsx',
mode: process.env.NODE_ENV,
devtool: isDev ? 'eval-source-map' : false,
output: {
path: PLUGINDIR,
filename: 'main.js',
libraryTarget: 'umd'
},
module: {
rules: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
loader: 'babel-loader',
options: {
plugins: ['transform-react-jsx']
}
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
}
]
},
resolve: {
extensions: ['.js', '.jsx', '.css']
}
};
webpack config also needs target: 'node'. Doing it just in .babelrc was not enough.

Migrating from Grunt+Bower to Webpack

I am trying to migrate away from Bower+Grunt to Webpack (and eventually to YARN instead of Bower).
However, any documentation I have come across for WebPack3 doesn't even talk about handling bower components.
WebPack 2 used a plugin for Bower, however the same isn't supported for WebPack 3.
Here's my WebPack config:
const webpack = require('webpack');
const path = require('path');
const frontEndConfig = {
entry: {
client: './client/app/app.js'
},
output: {
path: path.resolve(__dirname, 'dist/client/'),
filename: '[name].app.js'
},
module: {
loaders: [
{
test: /\.css$/,
loader: "style-loader!css-loader"
}
]
},
resolve: {
modules: ['bower_components'],
descriptionFiles: ['bower.json'],
}
};
const backEndConfig = {
entry: {
client: './server/app.js'
},
output: {
path: path.resolve(__dirname, 'dist/server/'),
filename: 'app.js'
},
module: {
loaders: [
{
test: /\.css$/,
loader: "style-loader!css-loader"
}
],
rules: [{
exclude: ['node_modules']
}]
},
resolve: {
modules: ['node_modules'],
descriptionFiles: ['package.json'],
}
};
module.exports = [
frontEndConfig,
backEndConfig
];;
The whole idea is to first run using webpack and then move completely to YARN.
They say plugins have been stopped for WebPack3, so what's the workaround for this?

Webpack, require is not a function

Getting an error when running my webpack-built React app - the error is as follows:
webpack-internal:///1495:3
var crypto = require('crypto');
^
TypeError: require is not a function
at eval (webpack-internal:///1495:3:14)
at Object.<anonymous> (/path/to/project/build/main.js:9739:1)
at __webpack_require__ (/path/to/project/build/main.js:21:30)
at eval (webpack-internal:///1494:1:20)
at Object.<anonymous> (/path/to/project/build/main.js:9733:1)
at __webpack_require__ (/path/to/project/build/main.js:21:30)
at eval (webpack-internal:///692:8:18)
at Object.<anonymous> (/path/to/project/build/main.js:4515:1)
at __webpack_require__ (/path/to/project/build/main.js:21:30)
at eval (webpack-internal:///1491:12:23)
I can't figure out which module this error is coming from. I am running my project by this command:
NODE_ENV=development nodemon --watch build/ build/main.js
Here is my webpack config:
const path = require('path')
const fs = require('fs')
const webpack = require('webpack')
const webpackConfig = {
context: path.join(__dirname, '..'),
entry: ['babel-polyfill', path.join(__dirname, '../src/entry.js')],
target: 'node',
output: {
path: path.resolve(__dirname, '../build'),
publicPath: '/',
libraryTarget: 'commonjs2',
filename: 'main.js'
},
resolve: {
modules: [
path.join(__dirname, '../src'),
path.join(__dirname, '../server'),
'node_modules'
],
extensions: ['.js', '.jsx', '.json']
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader'
},
{
test: /\.(png|gif|jpe?g|ico|eot|svg|ttf|woff2?)$/,
loader: 'file-loader',
options: {
context: 'src/app/assets/',
outputPath: 'dist/',
name: '[path][name].[ext]?[hash]',
//limit: 10000
}
}
]
},
node: {
net: 'empty',
tls: 'empty',
dns: 'empty',
fs: 'empty',
mysql: 'empty',
__dirname: true
},
plugins: [
// hot reload new webpack.HotModuleReplacementPlugin(),
new webpack.IgnorePlugin(/webpack-stats\.json$/),
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify('development'),
API_HOST: JSON.stringify(process.env.API_HOST),
API_PORT: JSON.stringify(process.env.API_PORT)
},
}),
],
externals: ['mysql', 'bindings']
}
if (process.env.NODE_ENV === 'development') {
webpackConfig.devtool = 'eval-source-map'
}
module.exports = webpackConfig
The file is being built with this command:
./node_modules/.bin/webpack --display-error-details --config webpack/webpack.config.js
The version of webpack I am using is 3.0.0.
If you still have a require in your bundle, it means that some ES6 file has not been transpiled by Babel.
I can see that you exclude node_modules from babel-loader...
Can you try removing the exclusion and see if it's any better?
Also, can you search for "require('crypto')" in all files arborescence?
Last, you say that it's a React app but babel-loader only transpiles .js files, not .jsx... Can you try changing loader's test to /\.jsx?$/ ?

Resources