Using Webpack with Foxx

You can use Webpack to compile your Foxx services the same way you would compile any other JavaScript code. However there are a few things you will need to keep in mind.

Basic configuration

Because the ArangoDB JavaScript environment is largely compatible with Node.js, the starting point looks fairly similar:

  1. "use strict";
  2. module.exports = {
  3. mode: "production",
  4. target: "node",
  5. output: {
  6. libraryTarget: "commonjs2"
  7. },
  8. externals: [/^@arangodb(\/|$)/]
  9. };

The service context

Foxx extends the module object with a special context property that reflects the current service context. As Webpack compiles multiple modules into a single file your code will not be able to access the real module object provided by ArangoDB.

To work around this limitation you can use the context provided by the @arangodb/locals module:

  1. const { context } = require("@arangodb/locals");

This object is identical to module.context and can be used as a drop-in replacement:

  1. const { context } = require("@arangodb/locals");
  2. const createRouter = require("@arangodb/foxx/router");
  3. const router = createRouter();
  4. context.use(router);

Externals

By default Webpack will attempt to include any dependency your code imports. This makes it easy to use third-party modules without worrying about filtering devDependencies but causes problems when importing modules provided by ArangoDB.

Most modules that are specific to ArangoDB or Foxx reside in the @arangodb namespace. This makes it fairly straightforward to tell Webpack to ignore them using the externals option:

  1. module.exports = {
  2. // ...
  3. externals: [/^@arangodb(\/|$)/]
  4. };

You can also use this to exclude other modules provided by ArangoDB, like the joi validation library:

  1. module.exports = {
  2. // ...
  3. externals: [/^@arangodb(\/|$)/, "joi"]
  4. };

Compiling scripts

As far as Webpack is concerned, scripts are additional entry points:

  1. const path = require("path");
  2. module.exports = {
  3. // ...
  4. context: path.resolve(__dirname, "src"),
  5. entry: {
  6. main: "./index.js",
  7. setup: "./scripts/setup.js"
  8. }
  9. };

Note: If your scripts are sharing a lot of code with each other or the rest of the service this can result in some overhead as the shared code will be included in each output file. A possible solution would be to extract the shared code into a separe bundle.