@@ -106,15 +106,22 @@ Let's break down this code step by step.
106106
107107### About Imports
108108
109+ In the Getting Started example, we used direct URL imports:
110+
109111``` typescript
110112import type { Entrypoint } from " jsr:@denops/std@^7.0.0" ;
111113```
112114
113- The first line imports the ` Entrypoint ` type from the [ @denops/std ] standard
114- library. You can find detailed information about the library by checking the
115- URL:
` https://jsr.io/@denops/[email protected] ` (replace
` jsr: ` to
` https://jsr.io/ ` ).
116- We fixed the version in the import URL, so it's recommended to check for details
117- and update to the latest version URL.
115+ However, with the recommended ` deno.jsonc ` configuration approach, this becomes:
116+
117+ ``` typescript
118+ import type { Entrypoint } from " @denops/std" ;
119+ ```
120+
121+ The import is resolved through the import map defined in ` deno.jsonc ` . The
122+ [ @denops/std ] standard library provides essential types and utilities for Denops
123+ plugin development. You can find detailed information about the library at
124+ ` https://jsr.io/@denops/std ` .
118125
119126Note that we use ` import type ` syntax, which is part of TypeScript's
120127[ Type-Only Imports and Export] ( https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html ) .
@@ -215,7 +222,7 @@ For example, use
215222Vim's function instead of ` denops.call ` like:
216223
217224``` typescript
218- import * as fn from " jsr: @denops/std@^7.0.0 /function" ;
225+ import * as fn from " @denops/std/function" ;
219226
220227// Bad (result1 is `unknown`)
221228const result1 = await denops .call (" expand" , " %" );
@@ -227,6 +234,232 @@ const result2 = await fn.expand(denops, "%");
227234If developers use ` function ` module instead, they can benefit from features like
228235auto-completion and type checking provided by LSP (Language Server Protocol).
229236
237+ ## Managing Dependencies with Workspace and Import Maps
238+
239+ > [ !IMPORTANT]
240+ >
241+ > The workspace configuration and import map features described below require
242+ > Denops v8.0.0 or later. For older versions, use direct URL imports in your
243+ > TypeScript files.
244+
245+ While the examples above use direct URL imports, the recommended approach for
246+ Denops plugins is to separate development configuration from runtime
247+ dependencies:
248+
249+ - ** Development configuration** : The root ` deno.jsonc ` with workspace settings
250+ enables development tools (` deno lint ` , ` deno fmt ` , etc.) to work from the
251+ project root
252+ - ** Runtime dependencies** : The plugin-specific ` deno.jsonc ` contains only the
253+ import map needed at runtime
254+ - ** No conflicts** : Since each Denops plugin has a unique directory under
255+ ` denops/ ` , their configuration files never conflict when installed
256+ - ** Clean separation** : Development tools configuration stays in the repository
257+ root, while runtime dependencies are isolated per plugin
258+ - ** Flexible format** : Both ` deno.json ` and ` deno.jsonc ` are supported, but
259+ ` deno.jsonc ` is recommended for its comment support
260+
261+ ### Separation of Development and Runtime Configuration
262+
263+ The workspace pattern serves two distinct purposes:
264+
265+ 1 . ** Development Time** : The root ` deno.jsonc ` enables development commands to
266+ work properly:
267+ ``` json
268+ {
269+ "workspace" : [
270+ " ./denops/your-plugin-name"
271+ ],
272+ "lint" : {
273+ "rules" : {
274+ "tags" : [" recommended" ]
275+ }
276+ },
277+ "fmt" : {
278+ "indentWidth" : 2
279+ }
280+ }
281+ ```
282+
283+ 2 . ** Runtime** : The plugin's ` deno.jsonc ` contains only what's needed for
284+ execution:
285+ ``` json
286+ {
287+ "imports" : {
288+ "@denops/std" : " jsr:@denops/std@^7.0.0"
289+ }
290+ }
291+ ```
292+
293+ ### Why This Separation Matters
294+
295+ When Vim/Neovim loads plugins, it merges all plugin directories into the runtime
296+ path. If runtime dependencies were in the root configuration file, they would
297+ conflict:
298+
299+ ```
300+ # After installation, plugins are merged:
301+ ~/.vim/pack/plugins/start/
302+ ├── plugin-a/
303+ │ ├── deno.jsonc # Development config (not used at runtime)
304+ │ └── denops/
305+ │ └── plugin-a/
306+ │ └── deno.jsonc # Runtime dependencies (unique path)
307+ └── plugin-b/
308+ ├── deno.jsonc # Development config (not used at runtime)
309+ └── denops/
310+ └── plugin-b/
311+ └── deno.jsonc # Runtime dependencies (unique path)
312+ ```
313+
314+ ### Setting up Your Plugin
315+
316+ 1 . Create a ` deno.jsonc ` in your repository root for development:
317+
318+ ``` json
319+ {
320+ "workspace" : [
321+ " ./denops/your-plugin-name"
322+ ],
323+ // Development-specific configuration
324+ "lint" : {
325+ "rules" : {
326+ "tags" : [" recommended" ]
327+ }
328+ },
329+ "fmt" : {
330+ "indentWidth" : 2 ,
331+ "lineWidth" : 80
332+ },
333+ "test" : {
334+ "include" : [" denops/**/*_test.ts" ]
335+ }
336+ }
337+ ```
338+
339+ 2 . Create a ` deno.jsonc ` inside your plugin directory for runtime dependencies:
340+
341+ ``` json
342+ // denops/your-plugin-name/deno.jsonc
343+ {
344+ "imports" : {
345+ "@denops/std" : " jsr:@denops/std@^7.0.0" ,
346+ "@denops/core" : " jsr:@denops/core@^7.0.0" ,
347+ "@core/unknownutil" : " jsr:@core/unknownutil@^4.3.0"
348+ }
349+ }
350+ ```
351+
352+ This separation ensures:
353+
354+ - Development tools like ` deno fmt ` and ` deno lint ` work from your project root
355+ - Runtime dependencies are properly resolved when the plugin is installed
356+ - No conflicts occur between multiple installed Denops plugins
357+
358+ ### Alternative: Using import_map.json(c)
359+
360+ While the examples above use ` deno.jsonc ` , Denops also supports
361+ ` import_map.json(c) ` files in the plugin directory:
362+
363+ ```
364+ denops/your-plugin-name/
365+ ├── import_map.jsonc # Alternative to deno.jsonc
366+ └── main.ts
367+ ```
368+
369+ However, there are important differences:
370+
371+ 1 . ** Import Maps Standard** (import_map.json) requires both entries for
372+ submodules:
373+ ``` json
374+ {
375+ "imports" : {
376+ "@denops/std" : " jsr:@denops/std@^7.0.0" ,
377+ "@denops/std/" : " jsr:@denops/std@^7.0.0/" // Required for submodules
378+ }
379+ }
380+ ```
381+
382+ 2 . ** deno.json Format** (recommended) needs only one entry:
383+ ``` json
384+ {
385+ "imports" : {
386+ "@denops/std" : " jsr:@denops/std@^7.0.0" // Handles both cases
387+ }
388+ }
389+ ```
390+
391+ > [ !IMPORTANT]
392+ >
393+ > We recommend using ` deno.jsonc ` over ` import_map.jsonc ` because:
394+ >
395+ > - It requires less verbose configuration
396+ > - It's the standard Deno configuration format
397+ > - It supports additional configuration options beyond imports
398+ > - Tools like ` deno add ` and ` deno remove ` work seamlessly with it
399+
400+ With this configuration, you can update your imports from:
401+
402+ ``` typescript
403+ import type { Entrypoint } from " jsr:@denops/std@^7.0.0" ;
404+ import { assert , is } from " jsr:@core/unknownutil@^4.3.0" ;
405+ ```
406+
407+ To cleaner import statements:
408+
409+ ``` typescript
410+ import type { Entrypoint } from " @denops/std" ;
411+ import { assert , is } from " @core/unknownutil" ;
412+ ```
413+
414+ ### Using npm packages
415+
416+ Import maps also simplify npm package usage. Instead of:
417+
418+ ``` typescript
419+ import { Maze } from " npm:@thewizardbear/maze_generator@^0.4.0" ;
420+ ```
421+
422+ Add it to your import map:
423+
424+ ``` json
425+ {
426+ "imports" : {
427+ "@denops/std" : " jsr:@denops/std@^7.0.0" ,
428+ "maze_generator" : " npm:@thewizardbear/maze_generator@^0.4.0"
429+ }
430+ }
431+ ```
432+
433+ Then import it as:
434+
435+ ``` typescript
436+ import { Maze } from " maze_generator" ;
437+ ```
438+
439+ ### Import Map Structure
440+
441+ The ` deno.json ` file in your Denops plugin directory should contain all the
442+ dependencies your plugin needs. This keeps dependency management isolated to
443+ each plugin while avoiding conflicts in the merged runtime directory.
444+
445+ For example, if your plugin uses additional npm packages:
446+
447+ ``` json
448+ {
449+ "imports" : {
450+ "@denops/std" : " jsr:@denops/std@^7.0.0" ,
451+ "@denops/std/" : " jsr:@denops/std@^7.0.0/" ,
452+ "@core/unknownutil" : " jsr:@core/unknownutil@^4.3.0" ,
453+ "your-npm-lib" : " npm:some-package@^1.0.0"
454+ }
455+ }
456+ ```
457+
458+ > [ !NOTE]
459+ >
460+ > Including both ` @denops/std ` and ` @denops/std/ ` allows you to import both the
461+ > main module and submodules (e.g., ` @denops/std/buffer ` ).
462+
230463## Next Steps
231464
232465In the next step, follow the tutorial to learn how to develop a minimum Denops
0 commit comments