-
-
Notifications
You must be signed in to change notification settings - Fork 296
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(rollup-plugin-import-meta-assets): init plugin #553
Merged
LarsDenBakker
merged 2 commits into
modernweb-dev:master
from
hsablonniere:rollup-plugin
Sep 20, 2020
Merged
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
*.js eol=lf |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
--- | ||
title: Rollup Plugin import-meta-assets | ||
eleventyNavigation: | ||
key: Rollup Plugin import-meta-assets | ||
parent: Building | ||
order: 2 | ||
--- | ||
|
||
Rollup plugin that detects assets references relative to modules using patterns such as `new URL('./path/to/asset.ext', import.meta.url)`. The assets are added to the rollup pipeline, allowing them to be transformed and hash the filenames. | ||
|
||
## Install | ||
|
||
Using npm: | ||
|
||
``` | ||
npm install @web/rollup-plugin-import-meta-assets --save-dev | ||
``` | ||
|
||
## Usage | ||
|
||
Create a rollup.config.js [configuration file](https://www.rollupjs.org/guide/en/#configuration-files) and import the plugin: | ||
|
||
```js | ||
import { importMetaAssets } from '@web/rollup-plugin-import-meta-assets'; | ||
|
||
export default { | ||
input: 'src/index.js', | ||
output: { | ||
dir: 'output', | ||
format: 'es', | ||
}, | ||
plugins: [importMetaAssets()], | ||
}; | ||
``` | ||
|
||
Then call `rollup` either via the [CLI](https://www.rollupjs.org/guide/en/#command-line-reference) or the [API](https://www.rollupjs.org/guide/en/#javascript-api). | ||
|
||
## Options | ||
|
||
### `exclude` | ||
|
||
Type: `String` | `Array[...String]`<br> | ||
Default: `null` | ||
|
||
A [picomatch pattern](https://github.com/micromatch/picomatch#globbing-features), or array of patterns, which specifies the files in the build the plugin should _ignore_. | ||
By default no files are ignored. | ||
|
||
### `include` | ||
|
||
Type: `String` | `Array[...String]`<br> | ||
Default: `null` | ||
|
||
A [picomatch pattern](https://github.com/micromatch/picomatch#globbing-features), or array of patterns, which specifies the files in the build the plugin should operate on. | ||
By default all files are targeted. | ||
|
||
### `warnOnError` | ||
|
||
Type: `Boolean`<br> | ||
Default: `false` | ||
|
||
By default, the plugin quits the build process when it encounters an error. If you set this option to true, it will throw a warning instead and leave the code untouched. | ||
|
||
### `transform` | ||
|
||
Type: `Function`<br> | ||
Default: `null` | ||
|
||
By default, referenced assets detected by this plugin are just copied as is to the output directory, according to your configuration. | ||
|
||
When `transform` is defined, this function will be called for each asset with two parameters, the content of the asset as a [Buffer](https://nodejs.org/api/buffer.html) and the absolute path. | ||
This allows you to conditionnaly match on the absolute path and maybe transform the content. | ||
|
||
In this example, we use it to optimize SVG images with [svgo](https://github.com/svg/svgo): | ||
|
||
```js | ||
import { importMetaAssets } from '@web/rollup-plugin-import-meta-assets'; | ||
const svgo = new SVGO({ | ||
// See https://github.com/svg/svgo#what-it-can-do | ||
plugins: [ /* plugins here */], | ||
}); | ||
|
||
export default { | ||
input: 'src/index.js', | ||
output: { | ||
dir: 'output', | ||
format: 'es', | ||
}, | ||
plugins: [ | ||
importMetaAssets({ | ||
transform: (assetBuffer, assetPath) => { | ||
return assetPath.endsWith('.svg') | ||
? svgo.optimize(assetBuffer.toString()).then(({ data }) => data); | ||
: assetBuffer; | ||
}, | ||
}), | ||
], | ||
}; | ||
``` | ||
|
||
## Examples | ||
|
||
Source directory: | ||
|
||
``` | ||
. | ||
├── one | ||
│ └── two | ||
│ └── the-image.svg | ||
├── | ||
└── entrypoint.js | ||
``` | ||
|
||
With `entrypoint.js` containing this: | ||
|
||
```js | ||
const imageUrl = new URL('./one/two/the-image.svg', import.meta.url).href; | ||
console.log(imageUrl); | ||
``` | ||
|
||
Output directory: | ||
|
||
``` | ||
. | ||
├── assets | ||
│ └── the-image.svg | ||
└── bundle.js | ||
``` | ||
|
||
With `bundle.js` containing this: | ||
|
||
```js | ||
const imageUrl = new URL(new URL('asset/the-image.svg', import.meta.url).href, import.meta.url) | ||
.href; | ||
console.log(imageUrl); | ||
``` |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
# Rollup Plugin import-meta-assets | ||
|
||
Rollup plugin that detects assets references relative to modules using patterns such as `new URL('./path/to/asset.ext', import.meta.url)`. The assets are added to the rollup pipeline, allowing them to be transformed and hash the filenames. | ||
|
||
## Install | ||
|
||
Using npm: | ||
|
||
``` | ||
npm install @web/rollup-plugin-import-meta-assets --save-dev | ||
``` | ||
|
||
## Usage | ||
|
||
Create a rollup.config.js [configuration file](https://www.rollupjs.org/guide/en/#configuration-files) and import the plugin: | ||
|
||
```js | ||
import { importMetaAssets } from '@web/rollup-plugin-import-meta-assets'; | ||
|
||
export default { | ||
input: 'src/index.js', | ||
output: { | ||
dir: 'output', | ||
format: 'es', | ||
}, | ||
plugins: [importMetaAssets()], | ||
}; | ||
``` | ||
|
||
Then call `rollup` either via the [CLI](https://www.rollupjs.org/guide/en/#command-line-reference) or the [API](https://www.rollupjs.org/guide/en/#javascript-api). | ||
|
||
## Documentation | ||
|
||
See [our website](https://modern-web.dev/docs/building/rollup-plugin-import-meta-assets/) for full documentation. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import cjsEntrypoint from './src/rollup-plugin-import-meta-assets.js'; | ||
|
||
const { importMetaAssets } = cjsEntrypoint; | ||
|
||
export { importMetaAssets }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
{ | ||
"name": "@web/rollup-plugin-import-meta-assets", | ||
"version": "0.0.0", | ||
"publishConfig": { | ||
"access": "public" | ||
}, | ||
"description": "Rollup plugin that detects assets references relative to modules using patterns such as `new URL('./path/to/asset.ext', import.meta.url)`. The assets are added to the rollup pipeline, allowing them to be transformed and hash the filenames.", | ||
"license": "MIT", | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/modernweb-dev/web.git", | ||
"directory": "packages/rollup-plugin-import-meta-assets" | ||
}, | ||
"author": "modern-web", | ||
"homepage": "https://github.com/modernweb-dev/web/tree/master/packages/rollup-plugin-import-meta-assets", | ||
"main": "dist/index.js", | ||
"engines": { | ||
"node": ">=10.0.0" | ||
}, | ||
"scripts": { | ||
"test": "npm run test:node", | ||
"test:node": "mocha test/**/*.test.js test/*.test.js", | ||
"test:update-snapshots": "mocha test/**/*.test.js test/*.test.js --update-snapshots", | ||
"test:watch": "npm run test:node -- --watch" | ||
}, | ||
"files": [ | ||
"dist" | ||
], | ||
"keywords": [ | ||
"rollup", | ||
"plugin", | ||
"import-meta" | ||
], | ||
"dependencies": { | ||
"@rollup/pluginutils": "^3.1.0", | ||
"estree-walker": "^2.0.1", | ||
"magic-string": "^0.25.7" | ||
} | ||
} |
109 changes: 109 additions & 0 deletions
109
packages/rollup-plugin-import-meta-assets/src/rollup-plugin-import-meta-assets.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
'use strict'; | ||
|
||
const fs = require('fs'); | ||
const path = require('path'); | ||
const { createFilter } = require('@rollup/pluginutils'); | ||
const { asyncWalk } = require('estree-walker'); | ||
const MagicString = require('magic-string'); | ||
|
||
/** | ||
* Extract the relative path from an AST node representing this kind of expression `new URL('./path/to/asset.ext', import.meta.url)`. | ||
* | ||
* @param {import('estree').Node} node - The AST node | ||
* @returns {string} The relative path | ||
*/ | ||
function getRelativeAssetPath(node) { | ||
const browserPath = node.arguments[0].value; | ||
return browserPath.split('/').join(path.sep); | ||
} | ||
|
||
/** | ||
* Checks if a AST node represents this kind of expression: `new URL('./path/to/asset.ext', import.meta.url)`. | ||
* | ||
* @param {import('estree').Node} node - The AST node | ||
* @returns {boolean} | ||
*/ | ||
function isNewUrlImportMetaUrl(node) { | ||
return ( | ||
node.type === 'NewExpression' && | ||
node.callee.type === 'Identifier' && | ||
node.callee.name === 'URL' && | ||
node.arguments.length === 2 && | ||
node.arguments[0].type === 'Literal' && | ||
typeof getRelativeAssetPath(node) === 'string' && | ||
node.arguments[1].type === 'MemberExpression' && | ||
node.arguments[1].object.type === 'MetaProperty' && | ||
node.arguments[1].property.type === 'Identifier' && | ||
node.arguments[1].property.name === 'url' | ||
); | ||
} | ||
|
||
/** | ||
* Detects assets references relative to modules using patterns such as `new URL('./path/to/asset.ext', import.meta.url)`. | ||
* The assets are added to the rollup pipeline, allowing them to be transformed and hash the filenames. | ||
* | ||
* @param {object} options | ||
* @param {string|string[]} [options.include] A picomatch pattern, or array of patterns, which specifies the files in the build the plugin should operate on. By default all files are targeted. | ||
* @param {string|string[]} [options.exclude] A picomatch pattern, or array of patterns, which specifies the files in the build the plugin should _ignore_. By default no files are ignored. | ||
* @param {boolean} [options.warnOnError] By default, the plugin quits the build process when it encounters an error. If you set this option to true, it will throw a warning instead and leave the code untouched. | ||
* @param {function} [options.transform] A function to transform assets. | ||
* @return {import('rollup').Plugin} A Rollup Plugin | ||
*/ | ||
function importMetaAssets({ include, exclude, warnOnError, transform } = {}) { | ||
const filter = createFilter(include, exclude); | ||
|
||
return { | ||
name: 'rollup-plugin-import-meta-assets', | ||
|
||
async transform(code, id) { | ||
if (!filter(id)) { | ||
return null; | ||
} | ||
|
||
const ast = this.parse(code); | ||
const magicString = new MagicString(code); | ||
|
||
await asyncWalk(ast, { | ||
enter: async node => { | ||
if (isNewUrlImportMetaUrl(node)) { | ||
const absoluteScriptDir = path.dirname(id); | ||
const relativeAssetPath = getRelativeAssetPath(node); | ||
const absoluteAssetPath = path.resolve(absoluteScriptDir, relativeAssetPath); | ||
const assetName = path.basename(absoluteAssetPath); | ||
|
||
try { | ||
const assetContents = await fs.promises.readFile(absoluteAssetPath); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. need to check if this works on node v10 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Will do. Official docs says v10. Local test with latest v10 works. |
||
const transformedAssetContents = | ||
transform != null | ||
? await transform(assetContents, absoluteAssetPath) | ||
: assetContents; | ||
const ref = this.emitFile({ | ||
type: 'asset', | ||
name: assetName, | ||
source: transformedAssetContents, | ||
}); | ||
magicString.overwrite( | ||
node.arguments[0].start, | ||
node.arguments[0].end, | ||
`import.meta.ROLLUP_FILE_URL_${ref}`, | ||
); | ||
} catch (error) { | ||
if (warnOnError) { | ||
this.warn(error, node.object.arguments[0].start); | ||
} else { | ||
this.error(error, node.object.arguments[0].start); | ||
} | ||
} | ||
} | ||
}, | ||
}); | ||
|
||
return { | ||
code: magicString.toString(), | ||
map: magicString.generateMap(), | ||
}; | ||
}, | ||
}; | ||
} | ||
|
||
module.exports = { importMetaAssets }; |
5 changes: 5 additions & 0 deletions
5
packages/rollup-plugin-import-meta-assets/test/fixtures/four.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 11 additions & 0 deletions
11
packages/rollup-plugin-import-meta-assets/test/fixtures/multi-level-entrypoint.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import { imageOne, nameOne } from './one/one.js'; | ||
import { imageTwo, nameTwo } from './one/two/two.js'; | ||
import { imageThree, nameThree } from './one/two/three/three.js'; | ||
import { imageFour, nameFour } from './one/two/three/four/four.js'; | ||
|
||
console.log({ | ||
[nameOne]: imageOne, | ||
[nameTwo]: imageTwo, | ||
[nameThree]: imageThree, | ||
[nameFour]: imageFour, | ||
}); |
5 changes: 5 additions & 0 deletions
5
packages/rollup-plugin-import-meta-assets/test/fixtures/one.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions
5
packages/rollup-plugin-import-meta-assets/test/fixtures/one/one-deep.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions
2
packages/rollup-plugin-import-meta-assets/test/fixtures/one/one.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export const nameOne = 'one-name'; | ||
export const imageOne = new URL('../one.svg', import.meta.url).href; |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@LarsDenBakker there are no types right? why does the linting of types does not fail?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have no idea. I'm new here 😆
Is there another plugin source I can get inspiration from?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
potentially here https://github.com/modernweb-dev/web/blob/master/packages/rollup-plugin-copy/src/copy.js