mockttp icon indicating copy to clipboard operation
mockttp copied to clipboard

Can't use mockttp in the browser without a CommonJS bundler

Open BirdTho opened this issue 7 years ago • 8 comments

In the Readme, you have an in-depth tutorial that gives an example of the browser code in the format const mockttp = require('mockttp').getLocal(); which would work in Node.js but not in Chrome.

I know that AMD works in the browser, but the commonJS fashion of var = require('package') isn't browser-friendly. The guide shows that the browser and nodeJS code are of the same kind.

Is there a way to load commonJS properly in a browser like that? RequireJS vomits when I attempt that. Or can I simply rebuild the project to AMD?

What's missing?

BirdTho avatar Jun 27 '18 21:06 BirdTho

Ah, yes, right now it's not built for AMD I'm afraid.

Building for Common JS like this means it works out of the box in both Node & with tools like Webpack/Browserify/Parcel/etc, but no, not with RequireJS (which, to be fair, has rather fallen out of popularity in recent years). You can see an example of this in Mockttp's tests if you're interested: within the Karma config there's an embedded webpack configuration, which both compiles all the TS, and bundles all required CommonJS modules into something that'll run in a browser en route.

Adding built-in AMD support is harder to do than you'd think I'm afraid. It's very easy to get TypeScript to output AMD code, but Mockttp itself requires various other modules internally, and you'd need all of them to be AMD-compatible as well, and their dependencies too, and for all of that to consistently use module identifiers throughout that will resolve happily with your final downstream require config too.

Imo, the easiest solution to all that would be to define a single prebuilt browser bundle here, which uses webpack or similar to bundle up all the necessary dependencies into one single UMD file, which anybody not using a CommonJS-capable build tool can use. Would that solve your problems? I'm unlikely to get to that soon myself, but I'd happily accept a PR to do so.

pimterry avatar Jun 27 '18 21:06 pimterry

I see you originally posted this with an error where Mockttp wasn't building too btw. I assume you've fixed that - out of interest, what was the issue? If there's any extra steps that it would've been useful to have in the readme to get you started, just let me know.

pimterry avatar Jun 27 '18 21:06 pimterry

Ah. Yes, for commonJS to work in any form, I'd need all the modules downloaded before the require calls are run. I have not learned Webpack yet.

I was trying to build it with AMD, but then I saw that its dependencies didn't afford me the opportunity to compile them to AMD - they shipped in commonJS. So I saw what you are saying.

I could venture into webpack. See if I can set up a bundled script.

BirdTho avatar Jun 27 '18 21:06 BirdTho

Well, I had typescript errors, but I noticed they were based on missing modules, so I made sure then to npm install.

At first, I was trying to build it from a node_modules folder int he project for which I wish to use it, but then I noticed among other things, that the npm install mockttp didn't copy over tsconfig.json among others. So I cloned it into its own folder and once I made sure to install typescript and rimraf and run an npm install, it worked.

  • note for requiring a full clone of mockttp

  • Note for npm install -g rimraf typescript

  • Note for regular npm install

  • Note for npm run build

BirdTho avatar Jun 27 '18 21:06 BirdTho

(If you would believe, at my company, I work on an advertising web player, and to keep size down I use plain old file concatenation. AMD adds a lot of fluff for all its niceties)

BirdTho avatar Jun 27 '18 21:06 BirdTho

Ok, sounds like a plan! Let me know if you have any questions.

Yes, you'll need to npm install first. You shouldn't need to separately install typescript or rimraf I think - a single npm install should give you everything.

I've worked in those kind of environments too. Simple tools like that can be useful sometimes, but they do get limiting once you start trying to do anything more complicated.

pimterry avatar Jun 27 '18 21:06 pimterry

I got a bundle built with this command

mxp-sea-0261:mockttp cthomas$ webpack-cli --entry ./dist/main-browser.js --output lib/mockttp-browser.js --mode development

I had to modify main-browser.ts to have a creation of window.Mockttp = {} with the getLocal, getRemote, and getStandalone functions attached to it though. It doesn't have anything fancy to tie it down to AMD or another module framework.

function getLocal(options: MockttpOptions = {}): Mockttp { return new MockttpClient(options); }

function getRemote(options: MockttpOptions = {}): Mockttp { return new MockttpClient(options); }

function getStandalone(options: any = {}): never { throw new Error('Cannot set up a standalone server within a browser'); }

declare global { interface Window { Mockttp: any; } }

window.Mockttp = window.Mockttp || {};

window.Mockttp.getLocal = getLocal; window.Mockttp.getRemote = getRemote; window.Mockttp.getStandalone = getStandalone;

BirdTho avatar Jun 27 '18 22:06 BirdTho

Nice! That looks promising.

You should be able to get webpack to generate those last bits itself for you too. Take a look at https://webpack.js.org/configuration/output/#output-librarytarget. I've never tried it, but in principle you can build with libraryTarget: 'umd' in your config and it should work out how to create a UMD module that'll automatically work with AMD, CommonJS or global variables, depending on the environment.

pimterry avatar Jun 29 '18 17:06 pimterry