---
tags: [module, server module, import, export, glide API, third-party library, code reuse, servicenow glide, quickstart, modular javascript, modern]
---
# JavaScript Modules

JavaScript modules are the **modern, preferred approach** for all server-side code in Fluent projects. Modules support `import`/`export`, provide access to typed Glide APIs via `@servicenow/glide`, enable code reuse across your application, and integrate with third-party npm libraries.

## When to Use

Use modules for server-side scripts in APIs that accept function types. Not all APIs support modules — some `script` properties only accept strings. If the compiler or build rejects a module import (for example, a type error such as `Type '() => void' is not assignable to type 'string'`, or a similar diagnostic), the API does not support modules and you should use `Now.include()` instead (see the `now-include-guide` topic). The exact error will vary depending on the structure of your module export and the API you're targeting.

**APIs that support modules (accept functions):**
- BusinessRule, ScriptAction, UiAction — `script` property
- RestApi route handlers — `script` property
- CatalogItemRecordProducer — `script` and `postInsertScript` properties
- ScheduledScript — `script` property

**APIs that require Now.include() or inline strings:**
- ScriptInclude, ClientScript — `script` is string-only
- CatalogClientScript, CatalogUiPolicy, UiPolicy — script fields are string-only
- SPWidget — all script fields are string-only
- Record API — data values are strings

### Additional use cases

- Organizing reusable server-side code into importable files
- Importing Glide APIs (`gs`, `GlideRecord`, etc.) for use in module files
- Adding third-party npm libraries to an application

## Instructions

1. **Module file location in src** Module files must be placed in the `serverModules` directory defined in `now.config.json`, which defaults to `src/server`
2. **Import Glide APIs explicitly:** In module files, `gs`, `GlideRecord`, and other Glide APIs are NOT automatically available. You must import them from `@servicenow/glide`. Analyze your script for ALL ServiceNow APIs used and import each one.
3. **Exception -- Script Include classes:** When writing Script Include class files (`Class.create` pattern), do NOT import Glide APIs. They are automatically available in Script Include execution context. Only import other Script Include classes from `@servicenow/glide/<scopeName>`.
4. **Use `export`/`import` in modules, `require` in scripts:** Modules use ES module syntax (`export`/`import`). Business rules, script includes, and other server scripts use `require` to consume module exports.
5. **Declare dependencies in package.json:** Third-party npm libraries must be declared in `dependencies`. Never modify versions of existing dependencies unless explicitly requested.
6. **Verify Glide API methods exist:** Only use methods explicitly defined in `@servicenow/glide` type definitions. Do not assume methods exist based on naming conventions.
7. **Use `GlideDateTime` instead of `gs.nowDateTime()`** -- `gs.nowDateTime()` is not allowed in scoped applications.
8. **Use Typescript** for creating module code unless instructed to use Javascript explicitly

## Key Concepts

### Import Patterns

- **Glide APIs in modules:** `import { gs, GlideRecord } from '@servicenow/glide'`
- **Namespaced APIs:** `import { RESTAPIRequest } from '@servicenow/glide/sn_ws_int'`
- **Script Include classes:** `import { MyClass } from '@servicenow/glide/x_my_scope'`
- **Module code in scripts:** `const { myFunction } = require('path/to/module')`

### Script Include Module Rules

This is the most common source of errors:

- **Module files with normal functions** -- MUST import Glide APIs from `@servicenow/glide`
- **Module files with Script Include classes (`Class.create`)** -- must NOT import Glide APIs (they are auto-available)
- **Consuming Script Include classes from other modules** -- import from `@servicenow/glide/<scopeName>`

### Exposing Modules Through Script Includes

Many platform features still require script includes — GlideAjax, cross-scope APIs, and extension points that call script includes by name. When your logic lives in a module but needs to be accessible through these mechanisms, create a script include that acts as a thin bridge using `require()`. See the "Bridging Modules Through Script Includes" section in the `script-include-guide` topic for the full pattern and examples.

### Subpath Imports

Use subpaths in `package.json` to create shorthand imports:

```json
{
    "imports": {
        "#calc": "calculus",
        "#derivative": "calculus/derivative"
    },
    "dependencies": {
        "calculus": "1.0.0"
    }
}
```

Then use the shorthand:

```typescript fluent
import { derivative } from '#derivative'
import * as calculus from '#calc'
```

### Limitations

- Modules work only within the application scope -- no cross-scope module sharing
- Node.js APIs are not supported
- Third-party libraries cannot access ServiceNow APIs such as GlideRecord and other imports from `@servicenow/glide`
- CommonJS modules from third-party libs are not supported unless they define exports
- Only a subset of ECMAScript features are supported

## Avoidance

- **Never use Glide APIs without importing them in module files** -- they are NOT globally available in module context
- **Never import Glide APIs in Script Include class files** -- they ARE globally available in that context
- **Never reference Script Include classes via global scope prefix in modules** -- `new x_myapp.MyUtils()` only works in non-module server scripts. In modules, it throws a runtime error (`x_myapp is not defined`). Always use `import { MyUtils } from '@servicenow/glide/x_myapp'` instead.
- **Never use methods not in `@servicenow/glide` type definitions** -- ServiceNow's Glide objects have specific, limited APIs
- **Never modify existing dependency versions in package.json** -- only add new dependencies
- **Never use `gs.nowDateTime()` in scoped apps** -- use `new GlideDateTime().getDisplayValue()` instead

## Examples

### Full Pattern: Business Rule with Module

This is the recommended pattern for server-side scripts. Write the logic in a module file and import it in the `.now.ts` definition:

**Fluent definition** (`src/fluent/business-rules/validate-request.now.ts`):

```typescript fluent
import '@servicenow/sdk/global'
import { BusinessRule } from '@servicenow/sdk/core'
import { validateRequest } from '../../server/business-rules/validate-request'

BusinessRule({
    $id: Now.ID['validate-request'],
    name: 'Validate Request',
    table: 'x_myapp_request',
    when: 'before',
    action: ['insert', 'update'],
    script: validateRequest,
})
```

**Module file** (`src/server/business-rules/validate-request.ts`):

```typescript fluent
import { gs, GlideRecord } from '@servicenow/glide'

export function validateRequest(current: GlideRecord<'x_myapp_request'>, previous: GlideRecord<'x_myapp_request'>) {
    var title = current.getValue('short_description');
    if (!title) {
        gs.addErrorMessage('Short description is required');
        current.setAbortAction(true);
    }
}
```

### Exporting from a Module

```typescript fluent
function myFunction() {}
const myVariable = 'value'

// Named exports for multiple features
export { myFunction, myVariable }
```

### Importing in Another Module

```typescript fluent
import { feature } from 'path/to/module'
```

### Importing in a Server Script (Business Rule, etc.)

```typescript fluent
const { feature } = require('path/to/module')
```

### Importing Glide APIs in a Module

```typescript fluent
import { gs } from '@servicenow/glide'
import { GlideRecord } from '@servicenow/glide'

// Namespaced APIs
import { RESTAPIRequest, RESTAPIResponse } from '@servicenow/glide/sn_ws_int'
```

### Using Script Include Classes from Modules

```typescript fluent
import { RecordUtils } from '@servicenow/glide/x_my_scope'

export function onRecordInsert(current, previous) {
    var recordUtils = new RecordUtils()
}
```

### Adding Dependencies in package.json

```json
{
    "name": "test",
    "version": "1.0.0",
    "dependencies": {
        "math": "1.0.0"
    }
}
```

When adding new dependencies, NEVER modify the versions of existing dependencies. Only add the new entry.
