Webpack 2: fixing build error on fetch polyfill - javascript

I've a JavaScript ES6 development environment with webpack 2.2.1 where I'm developing an application package-a.
I'm also using this environment for managing a development dependency on package-b which is defined by using npm link.
The environment works well.
Now I need to polyfill the fetch API that is used by package-b.
So whatwg-fetch has ben installed.
The polyfilling way I'm using is the one suggested in this discussion: https://gist.github.com/Couto/b29676dd1ab8714a818f#gistcomment-1584602
So I'm not calling import 'whatwg-fetch' on my code but I've this in my webpack configuration:
plugins: [
new webpack.ProvidePlugin({
'Promise': 'es6-promise',
'fetch': 'imports-loader?this=>global!exports-loader?global.fetch!whatwg-fetch',
'Headers': 'imports-loader?this=>global!exports-loader?global.Headers!whatwg-fetch'
}),
...
This always worked well for me, and also works if I use fetch from my main (package-a) module but as I use fetch in the dependency I get this traceback:
ERROR in ../package-b/~/imports-loader?this=>global!../package-b/~/exports-loader?global.fetch!../ecmwf-prwa-editor/~/whatwg-fetch/fetch.js
Module build failed: Error: "...package-b/node_modules/whatwg-fetch/fetch.js" is not in the SourceMap.
Note that the traceback contains ref to the package-b node_modules directory (where whatwg-fetch is installed as a development dependency only as I want to keep in "pure" and without automatically polifyll host env).
Removing the development dependency and removing it from node_modules change the traceback:
ERROR in ../package-b/src/something/something.js
Module not found: Error: Can't resolve 'whatwg-fetch' in '/Users/keul/.../package-b/src/something'
...
If I drop this way of polyfilling and simply I put import 'whatwg-fetch' on package-a all works normally.
Question is: what's happening here? I'm developing a package where the dependency is present, why the polyfill through webpack is failing in this case? There' a way to fix it?

Related

Bundling pouchdb-adapter-memory with Rollup

I am attempting to use the memory adapter for PouchDB. I want to bundle my application (along with dependencies like Pouch and this adapter) using Rollup. In order to reduce this to a minimally reproducible issue imagine this is my application I want to bundle:
import PouchDB from 'pouchdb-browser'
import MemoryAdapterPlugin from 'pouchdb-adapter-memory'
PouchDB.plugin(MemoryAdapterPlugin)
Since I am using a node module I'm obviously going to need the rollup-node-resolve Rollup plugin. Also many of PouchDB's dependent modules are in CJS format so I'm going to also need the rollup-node-commonjs Rollup plugin. Finally PouchDB makes use of some built-in Node modules (such as events) and the memory adapter even more (buffer, etc). I'm not sure these are used at runtime (it may be just in PouchDB's code because it can work in Node or the browser) but to prevent a bundling error I'm going to also include the rollup-plugin-polyfill-node plugin but direct the resolve plugin to prefer built-ins to the browser target if they are needed and available.
With all that in place here is my rollup config:
import commonjs from '#rollup/plugin-commonjs'
import resolve from '#rollup/plugin-node-resolve'
import polyfillNode from 'rollup-plugin-polyfill-node'
export default {
input: 'index.js',
output: {
format: 'iife',
name: 'app',
file: 'bundle.js'
},
plugins: [
commonjs({
requireReturnsDefault: "auto",
}),
polyfillNode(),
resolve({
preferBuiltins: true,
browser: true
}),
]
}
This will bundle. But when I load up the bundle in a browser I get an error about the inherits polyfill not working at this line:
https://github.com/FredKSchott/rollup-plugin-polyfill-node/blob/main/polyfills/inherits.js#L7
It says superCtor is undefined. If I step back a level on the backtrace it comes from this line:
https://github.com/nodejs/readable-stream/blob/main/lib/_stream_duplex.js#L46
The Readable is undefined. When I bundle I get warnings about circular references. I think it fundementally revolves around the fact that some of the PouchDB dependencies use NPM packages as polyfills explicitly (like inherits and readable-stream) while the polyfillNode plugin is also providing some of those same polyfills and they are doing so in an incompatible way. But I don't know how to untangle it.
Finally was able to resolve this so going to provide the answer in case someone else needs to bundle PouchDB memory adapter in Rollup.
The readable streams polyfill is a mess of circular dependencies. This is fine under a CJS format but since Rollup converts CJS to ES format it becomes problematic as Rollup can't figure out the proper order to put things in. This leads to the use of inherits where the superclass is not yet defined. The readable streams polyfill has an open ticket regarding this. The general solution is to fix it upstream in Node and then cut a new copy of the polyfill based on that upstream fix. The upstream fix was made but the polyfill hasn't yet been updated. Once it is this should naturally resolve itself.
In the meantime we can use someone else's fork of the polyfill that has the circular dependencies resolved. This fork is mentioned in that issue but the punchline is to add this to the package.json:
"readable-stream": "npm:vite-compatible-readable-stream#^3.6.0",
This will force readable-stream to resolve to that fork. But that's not the whole story. There are some dependencies of the memory adapter that are locked to a different version of readable-stream. To resolve that we want to add the following to our rollup's resolve plugin:
dedupe: ['readable-stream']
This will force the readable-stream substitute that we have explicitly added to our project to be used anytime a readable stream is needed.
The final issue is that PouchDB is using an ancient version of memdown that also has circular dependency issues. The latest version does not and seems to work with the memory adapter just fine. There is an open ticket at PouchDB to update memdown and this will naturally resolve when that happens.
In the meantime to resolve that we are going follow a similar pattern as above. We will explicitly require memdown into our project although no need for a fork. Just a newer version. Then to force the memory adapter to use this version we add memdown to that dedup option as well.

Error: Can't resolve 'net' after adding the rabbitode package to my React app

Just added rabbitode to my React TypeScript app so I can read from RabbitMQ. The instructions are quite straightforward, however, I hit a number of issues after installation. My module doesn't compile at all. There were a number of issues related to my using webpack 5, as described here this answer. Most of these could be resolved with the provided answer (util, buffer and querystring-es3) but I'm getting no joy with stream-browserify. Also, there are a couple of errors that I can't track down at all:
ERROR in ./node_modules/rabbitode/node_modules/amqplib/lib/connect.js 155:11-33
Module not found: Error: Can't resolve 'net' in 'c:\myapp\node_modules\rabbitode\node_modules\amqplib\lib'
ERROR in ./node_modules/rabbitode/node_modules/amqplib/lib/connect.js 157:11-33
Module not found: Error: Can't resolve 'tls' in 'c:\myapp\node_modules\rabbitode\node_modules\amqplib\lib'
The lines the error is about are:
if (protocol === 'amqp:') {
sock = require('net').connect(sockopts, onConnect);
}
else if (protocol === 'amqps:') {
sock = require('tls').connect(sockopts, onConnect);
}
else {
throw new Error("Expected amqp: or amqps: as the protocol; got " + protocol);
}
Thought this could be related to my node version as net and tls are available libraries
according to the docs but the issue remains.
Any idea about how to fix it??
Also, the stream error is:
ERROR in ./node_modules/rabbitode/node_modules/amqplib/lib/connection.js 18:13-37
Module not found: Error: Can't resolve 'stream' in 'c:\myapp\node_modules\rabbitode\node_modules\amqplib\lib'
BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.
If you want to include a polyfill, you need to:
- add a fallback 'resolve.fallback: { "stream": require.resolve("stream-browserify") }'
- install 'stream-browserify'
If you don't want to include a polyfill, you can use an empty module like this:
resolve.fallback: { "stream": false }
That I tried resolving by running npm install stream-browserify and adding stream: require.resolve("stream-browserify"), to the the fallback object in the webpack config. Why would this not work??
UPDATE
I think the problem is related to a couple of key facts:
I bootstrapped my application with the create-react-app and therefore by webpack config was ignored
rabbitode is relying on packages that were not meant for browser use.
I think the solution here is to look for a library that is more fit for purpose (or add an SseEmitter into my SpringBoot backend that reads from the queue, then read its contents in the client via an EventSource
I'm the author of the package, unfortunately it's not meant for use on frontend applications it's meant for node.js servers.
If you did find a workaround to get it working on the frontend I'd love to hear it and I'll see if I can add native support to it :)
Thanks
Evan

Unable to compile and publish my Typescript library using webpack or TSC

Ive created a library that helps to trace an object state using rx streams and
Im trying to publish it to npm community.
you can check this out In my github repo
I want to compile my library to a single Javascript file and also create a declaration file ".d.ts" for Typescript users.
As i understand, when running $ npm publish i release my entire repository. what i want is to release the dist folder with the library source and declaration file and so the end users will be able to debug my library if necessary through their code so i need also source map.
So first i need to compile my src directory to a single javascript file and i have 2 ways to do so, using tsc or with webpack.
What ive tried so far and you should know:
I used module alias, configured in tsconfig.json.
I separated the library's bussiness logic to multiple files.
I wanted to import internal library's modules using "#lib" prefix.
so in my tsconfig.json i added:
"paths": {
"#lib/*": [
"src/*"
]
},
That alone cause some problems.
first of all running the command:
$ tsc src/index.ts
doesn't work at all and it shows me an error:
src/index.ts(3,15): error TS2307: Cannot find module '#lib/state-traceable'.
src/index.ts(4,15): error TS2307: Cannot find module '#lib/traceable-decorator'. src/index.ts(5,15): error TS2307: Cannot find module '#lib/effect-decorator'.
src/index.ts(6,15): error TS2307: Cannot find module '#lib/meta'.
yet running the command:
$ tsc
does actually works but it compiles each source file and create declaration file for each one of them.
Additionally, it preserves the path alias "#lib/*" instead of compiling it to something javscript compatible with relative paths "../", "./" etc...
Using webpack:
I succeed to bundle all my library sources to a single file and get rid of the "#lib" prefix however im not able to create a single declaration file.
im using "awesome-typescript-loader" plugin for webpack.
I created an issue, thought its a bug but i yet received any response from them:
https://github.com/s-panferov/awesome-typescript-loader/issues/559
Also tried to get some help from Gitter chats, Typescript community, "awesome-typescript-loader" library has no dedicated chat but couldn't find any useful information. Most of the examples ive seen, Typescript library publishers used to create a single file in their source directory: "index.ts" and it makes life easier because you can use tsc and compile that single file to a javascript file.
I hope i will find salvation here.
Some general info about the environment itself:
OS: Windows 10 Pro
Node Version: 9.5.0
npm version: 5.6.0
webpack version: 4.2.0
Please use the path configuration like below
"paths": {
"#lib/state-traceable": ["src/state-traceable.ts"],
"#lib/meta": ["src/meta.ts"],
"#lib/effect-decorator": ["src/effect-decorator.ts"],
"#lib/traceable-decorator": ["src/traceable-decorator.ts"],
"#lib/contracts/*": ["src/contracts/*"],
"#lib/utils/*": ["src/utils/*"],
"#lib/rx-operators/*": ["src/rx-operators/*"]
},

Bootstrap v4 runtime/load error in Aurelia

I have the following in my aurelia.json file, among the rest of what you'd usually find. I copied it directly from the reference implementation, and as you'd therefore expect, it works fine.
{
'build': {
'bundles': [
'name': 'vendor-bundle.js'
'dependencies': [
"jquery",
{
"name": "bootstrap",
"path": "../node_modules/bootstrap/dist",
"main": "js/bootstrap.min",
"deps": ["jquery"],
"exports": "$",
"resources": [
"css/bootstrap.css"
]
}
]
]
}
}
However, I'm trying to migrate to Bootstrap 4, and it just doesn't seem to be working. In order to update the package, I've tried changing build.bundles.dependencies[].path to ../jspm_packages/github/twbs/bootstrap#4.0.0-beta as well as to ../node_modules/bootstrap-v4-dev/dist, but it doesn't change the error code or make the error manifest any less. I've also tried copying the v4 files into the dist folder for v3, which also causes the same problem.
Build is always clean; the error occurs at run-time:
DEBUG [templating] importing resources for app.html
Uncaught TypeError: plugin.load is not a function
Unhandled rejection Error: Failed loading required CSS file: bootstrap/css/bootstrap.css
EDIT:
Thanks to Ashley Grant's answer, I have updated Bootstrap through NPM, obviating any changes to aurelia.json. The error remains unchanged, which would seem to indicate a bug were it not for the fact that other people have successfully performed this migration without errors using the same toolchain.
EDIT2:
I've created steps to reproduce the bug:
$ au new
name # can be any valid value
2 # Selects TypeScript as the language
1 # Create project structure
1 # Install dependencies
cd into the project directory.
Add the two entries listed above to build.bundles[1].dependencies in aurelia_project/aurelia.json
$ npm install jquery --save
$ npm install bootstrap#^4.0.0-beta --save
Change src/app.html to the following:
<template>
<require from="bootstrap/css/bootstrap.css"></require>
</template>
Finally, execute either of the following and browse to the provided URL.
$ au run
OR
$ au build
$ serve
This yields the errors described in both Google Chrome Version 55.0.2883.87 (64-bit) and Mozilla Firefox 55.0.3 on my Arch Linux systems. I've not yet had the opportunity to test it on other systems.
Edit3:
Thanks to #vidriduch, everything appears to be working. However, if you look at the console, you find the following:
Uncaught SyntaxError: Unexpected token export
vendor-bundle.js:3927Uncaught Error: Mismatched anonymous define() module: [entirety of vendor-bundle.js printed here]
These are the two very first messages when the page loads in debug mode, but no other errors arise.
You are missing popper.js dependency for Bootstrap 4.0.0-beta.
In order for Aurelia to accept this add
"node_modules/popper.js/dist/umd/popper.js"
on the top (as per comment from #hxtk) of prepend part of aurelia.json (assuming that you are using RequireJS, otherwise have a look at webpack dependency linking for Bootstrap https://getbootstrap.com/docs/4.0/getting-started/webpack/)
Just to mention, the version of popper.js you need to install is 1.11.0 (https://github.com/twbs/bootstrap/issues/23381), so
npm install popper.js#1.11.0
or
yarn add popper.js#1.11.0
and it should work :)
Your aurelia.json configuration is correct. I'm going to guess you never ran npm install bootstrap#^4.0.0-beta --save as you are mentioning copying files in to a versioned node_modules folder, and NPM doesn't use versioned folders like JSPM does.
So run npm install bootstrap#^4.0.0-beta --save and things should start working. I have your exact configuration working in an application for one of my clients.

Using node modules with Rollup to build web client

I'm trying to build a react application using rollup instead of browserify and babel. I realize I need to use the rollup-plugin-babel to transpile jsx, but when I tell rollup the format is iife, the final page loads with an error:
Uncaught ReferenceError: React is not defined
What do I need to add to the rollup.config.js to include the node modules I've installed in package.json in my final build?
Two options:
Include React as a separate <script> tag before your app bundle
Include rollup-plugin-node-resolve in your config file, to pull in dependencies from your node_modules folder.
If you take the second route you'll also need rollup-plugin-commonjs (to convert the CommonJS module into an ES module). I think you would also need to add import * as React from 'react' to each module that contained JSX, otherwise you'll continue to get the ReferenceError.
Note: you might be able to use rollup-plugin-buble to transpile JSX. It's similar to the Babel plugin but much faster (though it doesn't transpile every ES2015 feature)

Categories

Resources