Web Accessible Resources vs index.d.ts: Understanding the Difference in Browser Extension Development
I’ve been getting this question a lot lately from fellow developers working on browser extensions: What’s the real difference between Web Accessible Resources and index.d.ts, and when should I use each one? Let me break it down based on my experience building extensions.
What are these things anyway?
At their core, they solve completely different problems:
- Web Accessible Resources: Let web pages access files from your extension (runtime resources)
- index.d.ts: Tell TypeScript how your code should work (development-time types)
Think of one as a “pass” for the browser, and the other as a “manual” for developers.
The core difference: Runtime vs Development-time
Web Accessible Resources - Actual files at runtime
Web Accessible Resources are files in your extension that web pages can directly access. Things like images, CSS files, JavaScript libraries, etc.
// Access them in your code like this
const imageUrl = chrome.runtime.getURL('assets/icon.png')These files actually exist in your packaged extension, and web pages can load them using chrome-extension:// URLs.
index.d.ts - Type definitions for development
index.d.ts is a TypeScript declaration file that only matters during development. It doesn’t even make it into your final extension package.
// Define environment variable types in index.d.ts
declare namespace NodeJS {
interface ProcessEnv {
PLASMO_PUBLIC_API_URI?: string
STRIPE_PRIVATE_KEY?: string
}
}This file basically tells TypeScript: “Hey, these variables should have these types,” giving you better code completion and error checking during development.
When to use each one
When to reach for Web Accessible Resources
Use them when you need web pages to access your extension’s files:
- Expose static assets: Images, CSS, JSON data files
- Integrate third-party libraries: Library files that need to run in webpage context
- Share HTML pages: Let web pages open specific pages from your extension
// Configure in package.json
{
"manifest": {
"web_accessible_resources": [
{
"resources": ["assets/*.png", "resources/data.json"],
"matches": ["https://*.example.com/*"]
}
]
}
}When index.d.ts comes in handy
Use it when you need TypeScript type support:
- Environment variable types: Define types for
process.envvariables - Global type extensions: Add types to global objects
- Module declarations: Provide types for third-party libraries or custom modules
// After defining types in index.d.ts, you get better IntelliSense
const apiUrl = process.env.PLASMO_PUBLIC_API_URI // TypeScript knows this is string | undefinedMaking the right choice in real projects
Here’s how I think about it when working on extensions:
A practical example
Say you’re building an image processing extension:
Web Accessible Resources use cases:
- Expose CSS files for filter effects
- Let webpages load icons from your extension
- Share configuration data via JSON files
index.d.ts use cases:
- Define types for image processing API keys
- Provide types for custom image processing functions
- Environment variable type safety
Common pitfalls to avoid
- Don’t mix up their purposes: Web Accessible Resources are for the browser, index.d.ts is for developers
- Different build outcomes: The former gets packaged, the latter only helps during development
- Configuration locations: One goes in package.json, the other sits in your project root
The bottom line
Quick rule of thumb:
- Need webpage file access → Web Accessible Resources
- Want code completion and type safety → index.d.ts
Most decent-sized extension projects will use both. Web Accessible Resources handle runtime resource access, while index.d.ts ensures development-time type safety.
If you run into resource access or type definition issues while building your extensions, feel free to reach out and share your experiences!