After days of searching a solutions, I would much appreciate a bit of help!
The idea is simple: I would like to transpile a js code which use the node ‘buffer’ to pure ES5 so it can run on Duktape (duktape.org). (with webpack and babeljs)
The code have been simplified in a test.js
, which use buffer
and console
.
JS code src/test.js
:
import "core-js/stable"; // just in case it might help
const { Buffer } = require('buffer');
const buf1 = Buffer.alloc(10);
let a = 3;
console.log("BLAH");
webpack.config.js
const path = require('path');
const webpack = require('webpack');
// Provide code node modules in webpack 5+ (eg. path, stream, sys, timers, ...)
const NodePolyfillPlugin = require('node-polyfill-webpack-plugin');
module.exports = {
//mode: 'development', // otherwise it is using long evals which duktape doesn't like
mode: 'production',
target: 'es5',
entry: [
'core-js/stable',
'./src/test.js'
],
optimization: {
minimize: false,
},
plugins: [
// polyfill the nodejs modules
// use NodePolyfillPlugin instead of resolve.fallback(s) - both have been tried without success
new NodePolyfillPlugin({
onlyAliases: ['buffer', 'Buffer'],
}),
],
module: {
rules: [
{
test: /.(?:js|mjs|cjs)$/,
exclude: /node_modules/,
include: [ path.resolve(__dirname, "src") ],
use: ['babel-loader']
// options in .babelrc
// no targets -> scrictest environment => es5
}
]
},
output: {
filename: 'run-es5-sync-contacts.js',
path: path.resolve(__dirname, 'dist'),
chunkFormat: false,
// copy/past from webpack doc
environment: {
// The environment supports arrow functions ('() => { ... }').
arrowFunction: false,
// The environment supports async function and await ('async function () { await ... }').
asyncFunction: false,
// The environment supports BigInt as literal (123n).
bigIntLiteral: false,
// The environment supports const and let for variable declarations.
const: false,
// The environment supports destructuring ('{ a, b } = obj').
destructuring: false,
// The environment supports an async import() function to import EcmaScript modules.
dynamicImport: false,
// The environment supports an async import() when creating a worker, only for web targets at the moment.
dynamicImportInWorker: false,
// The environment supports 'for of' iteration ('for (const x of array) { ... }').
forOf: false,
// The environment supports 'globalThis'.
globalThis: false,
// The environment supports ECMAScript Module syntax to import ECMAScript modules (import ... from '...').
module: false,
// The environment supports optional chaining ('obj?.a' or 'obj?.()').
optionalChaining: false,
// The environment supports template literals.
templateLiteral: false,
},
},
performance: {
maxEntrypointSize: 2048000,
maxAssetSize: 2048000
},
};
.babelrc
(“targets” is explicitly omited so it use the strictest javascript standard: es5)
{
"presets": [
["@babel/preset-env", {
"debug": true,
"corejs": { "version": 3, "proposals": true },
"useBuiltIns": "usage",
"forceAllTransforms": true, // for stricter non-standard environment: duktape
"ignoreBrowserslistConfig": true
}]
]
}
The code is properly transpiled, yet, the final output include the code coming from nodes_modules/buffer/index.js which use the js keyword let
and const
, and therefore failed when executing it using duktape (as duktape does apparently not support let
and const
).
dist/run-es5-sync-contacts.js
still somewhere include the lines from buffer/index.js
:
...
Buffer.allocUnsafeSlow = function (size) {
return allocUnsafe(size)
}
function fromString (string, encoding) {
if (typeof encoding !== 'string' || encoding === '') {
encoding = 'utf8'
}
if (!Buffer.isEncoding(encoding)) {
throw new TypeError('Unknown encoding: ' + encoding)
}
const length = byteLength(string, encoding) | 0
let buf = createBuffer(length)
const actual = buf.write(string, encoding)
if (actual !== length) {
// Writing a hex string, for example, that contains invalid characters will
// cause everything after the first invalid character to be ignored. (e.g.
// 'abxxcd' will be treated as 'ab')
buf = buf.slice(0, actual)
}
return buf
}
...
Does anyone has an idea how to tell babeljs to transpile the code imported through NodePolyfillPlugin
(or directly specified with resolve.fallback
) to a strict ‘es5’ target?
I would expect that output.environment
does the trick, yet not for the nodejs modules polyfilled through NodePolyfillPlugin
nor resolve.fallback
.
I’ve look through all documentation, search for similar problems, tried many (!) combinations, the final code still use let
keywords.
Using let
directly in test.js
, is properly transpiled.
Tried setting resolve.fallback
instead of using NodePolyfillPlugin
, same result.
With the provided code, console
is expected to be missing.
Help will be greatly appreciated!
Jean-Luc is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.