https://github.com/ropean/inline-assets
A zero-dependency Vite plugin and standalone utility to inline CSS, JavaScript, and SVG assets into HTML for single-file deployment.
https://github.com/ropean/inline-assets
inline-assets
Last synced: 3 months ago
JSON representation
A zero-dependency Vite plugin and standalone utility to inline CSS, JavaScript, and SVG assets into HTML for single-file deployment.
- Host: GitHub
- URL: https://github.com/ropean/inline-assets
- Owner: ropean
- License: mit
- Created: 2025-10-27T19:51:58.000Z (9 months ago)
- Default Branch: main
- Last Pushed: 2025-11-21T19:57:23.000Z (8 months ago)
- Last Synced: 2025-11-21T20:12:20.368Z (8 months ago)
- Topics: inline-assets
- Language: Vue
- Homepage: https://inline.aceapp.dev
- Size: 227 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
# @ropean/inline-assets
[](https://github.com/ropean/inline-assets/actions/workflows/deploy-to-cloudflare.yml)
[](https://inline-assets.ropean.org)
[](https://github.com/ropean/inline-assets/blob/main/LICENSE)
[](https://www.npmjs.com/package/@ropean/inline-assets)
[](https://www.npmjs.com/package/@ropean/inline-assets)
A **zero-dependency** Vite plugin and standalone utility to inline CSS, JavaScript, and SVG assets into HTML for single-file deployment.
## โจ Features
- ๐ **Zero Dependencies** - No external packages required
- ๐ **Dual Mode** - Use as Vite plugin or standalone function
- ๐จ **Inline CSS** - Converts `` tags to `` tags
- ๐ฆ **Inline JavaScript** - Converts `<script src>` to inline `<script>`
- ๐ผ๏ธ **Inline SVG** - Converts SVG files to base64 data URIs
- ๐ฏ **Selective Inlining** - Exclude specific files with patterns
- ๐งน **Auto Cleanup** - Removes inlined files and empty directories
- ๐ **Custom Logger** - Bring your own logger or use the built-in one
- ๐ง **TypeScript Support** - Full type definitions included
## ๐ฆ Installation
```bash
npm install @ropean/inline-assets -D
```
```bash
yarn add @ropean/inline-assets -D
```
```bash
pnpm add @ropean/inline-assets -D
```
## ๐ Usage
### As a Vite Plugin
```typescript
// vite.config.ts
import { defineConfig } from 'vite';
import inlineAssets from '@ropean/inline-assets';
export default defineConfig({
plugins: [
inlineAssets({
css: true,
js: true,
svg: { img: false, link: true },
excludes: ['assets/large-file.js'],
}),
],
});
```
### As a Standalone Function
Perfect for use with **any build tool** (Webpack, Rollup, esbuild, etc.):
```javascript
import { inlineAssets } from '@ropean/inline-assets';
// After your build process
await inlineAssets({
htmlPath: './dist/index.html',
css: true,
js: true,
svg: { img: true, link: true },
});
```
### With Custom Logger
```javascript
import { inlineAssets } from '@ropean/inline-assets';
const myLogger = {
info: (msg) => console.log('[INFO]', msg),
success: (msg) => console.log('[โ]', msg),
warning: (msg) => console.warn('[โ ]', msg),
error: (msg) => console.error('[โ]', msg),
};
await inlineAssets({
htmlPath: './dist/index.html',
logger: myLogger,
});
// Or disable logging completely
await inlineAssets({
htmlPath: './dist/index.html',
logger: false,
});
```
## โ๏ธ Options
### Vite Plugin Options
```typescript
interface VitePluginOptions {
/** Whether to inline CSS files (default: true) */
css?: boolean;
/** Whether to inline JavaScript files (default: true) */
js?: boolean;
/** SVG inlining options (default: { img: false, link: true }) */
svg?:
| boolean
| {
img?: boolean; // Inline SVG in <img> tags
link?: boolean; // Inline SVG in <link> tags (favicon)
};
/** File patterns to exclude from inlining (default: []) */
excludes?: string[];
/** Distribution directory name (default: 'dist') */
distDir?: string;
/** HTML file name to process (default: 'index.html') */
htmlFileName?: string;
/** Where to insert inlined CSS (default: 'original') */
cssInsertPosition?: 'original' | 'head-start' | 'head-end';
/** Custom logger or false to disable (default: built-in logger) */
logger?: LoggerInterface | false;
}
```
### Standalone Function Options
```typescript
interface InlineAssetsOptions {
/** Path to the HTML file to process (required) */
htmlPath: string;
/** Base directory for resolving asset paths (default: HTML file's directory) */
baseDir?: string;
/** Whether to inline CSS files (default: true) */
css?: boolean;
/** Whether to inline JavaScript files (default: true) */
js?: boolean;
/** SVG inlining options (default: true) */
svg?:
| boolean
| {
img?: boolean;
link?: boolean;
};
/** File patterns to exclude from inlining (default: []) */
excludes?: string[];
/** Whether to delete inlined asset files (default: true) */
removeInlinedFiles?: boolean;
/** Whether to remove empty directories (default: true) */
cleanupEmptyDirs?: boolean;
/** Where to insert inlined CSS (default: 'original') */
cssInsertPosition?: 'original' | 'head-start' | 'head-end';
/** Custom logger or false to disable (default: built-in logger) */
logger?: LoggerInterface | false;
}
```
## ๐ Custom Logger Interface
Implement this interface to create your own logger:
```typescript
interface LoggerInterface {
info(message: string): void;
success(message: string): void;
warning(message: string): void;
error(message: string): void;
event?(message: string): void; // Optional
file?(path: string): string; // Optional
newline?(count?: number): void; // Optional
}
```
## ๐ฏ CSS Insert Position
Control where inlined CSS is placed in your HTML:
```javascript
inlineAssets({
cssInsertPosition: 'original', // Default: keep CSS at original <link> position
});
```
### Available Options
- **`'original'`** (default) - Keeps CSS at the original `<link>` tag position
- โ
Preserves the order of CSS and JS
- โ
CSS appears before JS if that's how you structured it
- โ ๏ธ May create multiple `<style>` tags if you have multiple CSS files
- **`'head-start'`** - Moves all CSS to the beginning of `<head>`
- โ
Optimal for performance (CSS loads first)
- โ
Single merged `<style>` tag
- โ ๏ธ Changes the original order
- **`'head-end'`** - Moves all CSS to the end of `<head>`
- โ
Single merged `<style>` tag
- โ ๏ธ CSS loads after other head elements
### Example
```javascript
// Keep CSS before JS (preserves order)
inlineAssets({
cssInsertPosition: 'original',
});
// Optimize for performance (CSS at top)
inlineAssets({
cssInsertPosition: 'head-start',
});
```
## ๐ฏ Exclusion Patterns
Exclude specific files from inlining:
```javascript
inlineAssets({
excludes: [
'index.js', // Matches any file named 'index.js'
'assets/vendor.js', // Matches 'assets/vendor.js' specifically
'large-image.svg', // Matches any file named 'large-image.svg'
],
});
```
## ๐ง How It Works
### Vite Plugin Mode
1. **Config Hook**: Automatically configures Vite to extract CSS as a single file
2. **Build**: Vite builds your project normally
3. **Close Bundle Hook**: After build completes, inlines assets into HTML
4. **Cleanup**: Removes inlined files and empty directories
### Standalone Mode
1. Reads the HTML file
2. Finds all CSS, JS, and SVG references
3. Inlines their content (CSS/JS as text, SVG as base64)
4. Writes the modified HTML back
5. Optionally removes inlined files
## ๐ Example Output
**Before** (3 files):
```
dist/
โโโ index.html
โโโ assets/
โ โโโ index.css
โ โโโ index.js
```
**After** (1 file):
```
dist/
โโโ index.html (with inlined CSS and JS)
```
## ๐ค Integration Examples
See the [`examples/`](examples/) directory for complete, runnable examples:
- ๐ **[Vite Plugin Usage](examples/vite-usage.js)** - Basic and advanced Vite plugin configurations
- ๐ง **[Standalone Function](examples/standalone-usage.js)** - Use with any build tool
- ๐ฆ **[Webpack Integration](examples/webpack-integration.js)** - Webpack plugin example
- ๐ฏ **[Rollup Integration](examples/rollup-integration.js)** - Rollup plugin example
- ๐ **[Gulp Integration](examples/gulp-integration.js)** - Gulp task example
- ๐ **[npm Scripts](examples/npm-script.js)** - Post-build script with error handling
- ๐จ **[CSS Insert Position](examples/css-insert-position.js)** - CSS positioning strategies
### Quick Start Examples
<details>
<summary><b>Webpack Integration</b></summary>
```javascript
// webpack.config.js
const { inlineAssets } = require('@ropean/inline-assets');
module.exports = {
plugins: [
{
apply: (compiler) => {
compiler.hooks.done.tap('InlineAssets', async () => {
await inlineAssets({ htmlPath: './dist/index.html' });
});
},
},
],
};
```
๐ [View full example](examples/webpack-integration.js)
</details>
<details>
<summary><b>Rollup Integration</b></summary>
```javascript
// rollup.config.js
import { inlineAssets } from '@ropean/inline-assets';
export default {
plugins: [
{
name: 'inline-assets',
closeBundle: async () => {
await inlineAssets({ htmlPath: './dist/index.html' });
},
},
],
};
```
๐ [View full example](examples/rollup-integration.js)
</details>
<details>
<summary><b>npm Scripts</b></summary>
```json
{
"scripts": {
"build": "vite build",
"postbuild": "node inline-assets.js"
}
}
```
```javascript
// inline-assets.js
import { inlineAssets } from '@ropean/inline-assets';
const result = await inlineAssets({
htmlPath: './dist/index.html',
});
if (!result.success) {
console.error('Failed to inline assets');
process.exit(1);
}
```
๐ [View full example with error handling](examples/npm-script.js)
</details>
<details>
<summary><b>Gulp Integration</b></summary>
```javascript
// gulpfile.js
import { inlineAssets } from '@ropean/inline-assets';
import gulp from 'gulp';
gulp.task('inline', async () => {
await inlineAssets({ htmlPath: './dist/index.html' });
});
gulp.task('build', gulp.series('your-build-task', 'inline'));
```
๐ [View full example with error handling](examples/gulp-integration.js)
</details>
## ๐ Troubleshooting
### CSS not inlining properly?
Make sure you're not using `cssCodeSplit: true` in your Vite config. The plugin automatically sets this to `false`.
### Assets not found?
Check that `baseDir` points to the correct directory where your assets are located.
### Want to keep some files external?
Use the `excludes` option to prevent specific files from being inlined.
## ๐ License
MIT ยฉ ropean
## ๐ Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
## ๐ฎ Issues
Found a bug or have a feature request? [Open an issue](https://github.com/ropean/inline-assets/issues)