-
Notifications
You must be signed in to change notification settings - Fork 143
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1001 from embroider-build/addon-dev
Create addon-dev package
- Loading branch information
Showing
22 changed files
with
545 additions
and
79 deletions.
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,7 @@ | ||
# compiled output | ||
/src/**/*.js | ||
/src/**/*.d.ts | ||
|
||
# dependencies | ||
/node_modules/ | ||
|
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,10 @@ | ||
# See https://help.github.com/ignore-files/ for more about ignoring files. | ||
|
||
# compiled output | ||
/src/**/*.js | ||
/src/**/*.d.ts | ||
/src/**/*.map | ||
|
||
# dependencies | ||
/node_modules/ | ||
|
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 @@ | ||
'use strict'; | ||
|
||
module.exports = { | ||
singleQuote: true, | ||
}; |
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 @@ | ||
# @embroider/addon-dev | ||
|
||
Utilities for working on v2 addons. | ||
|
||
## Rollup Utilities | ||
|
||
`@embroider/addon-dev/rollup` exports utilities for building addons with rollup. To use them: | ||
|
||
1. Add the following `devDependencies` to your addon: | ||
|
||
- @embroider/addon-dev | ||
- rollup | ||
- @babel/core | ||
- @rollup/plugin-babel | ||
|
||
2. Copy the `./sample-rollup.config.js` in this repo to your own `rollup.config.js`. | ||
|
||
## addon-dev command | ||
|
||
The `addon-dev` command helps with common tasks in v2 addons. | ||
|
||
- linking up a test application that is embedded within your addon's repo | ||
- synchronizing `devDependencies` from an embedded test application out into | ||
your addon's actual package.json | ||
|
||
(You can avoid the need for both of these if you keep your addon and its test app as separate packages in a monorepo instead.) | ||
|
||
## Contributing | ||
|
||
See the top-level CONTRIBUTING.md in this monorepo. | ||
|
||
## License | ||
|
||
This project is licensed under the MIT License. |
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,41 @@ | ||
{ | ||
"name": "@embroider/addon-dev", | ||
"version": "0.45.0", | ||
"description": "Utilities for addon authors", | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/embroider-build/embroider.git", | ||
"directory": "packages/addon-dev" | ||
}, | ||
"license": "MIT", | ||
"author": "Edward Faulkner <[email protected]>", | ||
"bin": { | ||
"addon-dev": "./src/commands.js" | ||
}, | ||
"exports": { | ||
"./template-colocation-plugin": "./src/template-colocation-plugin.js", | ||
"./rollup": "./src/rollup.js" | ||
}, | ||
"dependencies": { | ||
"@embroider/shared-internals": "^0.45.0", | ||
"@rollup/pluginutils": "^4.1.1", | ||
"fs-extra": "^10.0.0", | ||
"minimatch": "^3.0.4", | ||
"rollup-plugin-copy-assets": "^2.0.3", | ||
"rollup-plugin-delete": "^2.0.0", | ||
"walk-sync": "^3.0.0", | ||
"yargs": "^17.0.1" | ||
}, | ||
"devDependencies": { | ||
"@types/fs-extra": "^9.0.12", | ||
"@types/minimatch": "^3.0.4", | ||
"@types/yargs": "^17.0.3", | ||
"rollup": "^2.58.0" | ||
}, | ||
"engines": { | ||
"node": "12.* || 14.* || >= 16" | ||
}, | ||
"volta": { | ||
"extends": "../../package.json" | ||
} | ||
} |
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,41 @@ | ||
import babel from '@rollup/plugin-babel'; | ||
import { Addon } from '@embroider/addon-dev/rollup'; | ||
|
||
const addon = new Addon({ | ||
srcDir: 'src', | ||
destDir: 'dist', | ||
}); | ||
|
||
export default { | ||
// This provides defaults that work well alongside `publicEntrypoints` below. | ||
// You can augment this if you need to. | ||
output: addon.output(), | ||
|
||
plugins: [ | ||
// These are the modules that users should be able to import from your | ||
// addon. Anything not listed here may get optimized away. | ||
addon.publicEntrypoints(['components/**/*.js', 'index.js']), | ||
|
||
// These are the modules that should get reexported into the traditional | ||
// "app" tree. Things in here should also be in publicEntrypoints above, but | ||
// not everything in publicEntrypoints necessarily needs to go here. | ||
addon.appReexports(['components/welcome-page.js']), | ||
|
||
// This babel config should *not* apply presets or compile away ES modules. | ||
// It exists only to provide development niceties for you, like automatic | ||
// template colocation. | ||
babel({ | ||
plugins: ['@embroider/addon-dev/template-colocation-plugin'], | ||
}), | ||
|
||
// Ensure that standalone .hbs files are properly integrated as Javascript. | ||
addon.hbs(), | ||
|
||
// addons are allowed to contain imports of .css files, which we want rollup | ||
// to leave alone and keep in the published output. | ||
addon.keepAssets(['**/*.css']), | ||
|
||
// Remove leftover build artifacts when starting a new build. | ||
addon.clean(), | ||
], | ||
}; |
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,31 @@ | ||
import { readJsonSync, writeJsonSync } from 'fs-extra'; | ||
import minimatch from 'minimatch'; | ||
import type { Plugin } from 'rollup'; | ||
|
||
export default function appReexports(opts: { | ||
from: string; | ||
to: string; | ||
include: string[]; | ||
}): Plugin { | ||
return { | ||
name: 'app-reexports', | ||
generateBundle(_, bundle) { | ||
let pkg = readJsonSync('package.json'); | ||
let appJS: Record<string, string> = {}; | ||
for (let filename of Object.keys(bundle)) { | ||
if (opts.include.some((glob) => minimatch(filename, glob))) { | ||
appJS[`./${filename}`] = `./dist/_app_/${filename}`; | ||
this.emitFile({ | ||
type: 'asset', | ||
fileName: `_app_/${filename}`, | ||
source: `export { default } from "${pkg.name}/${filename}";\n`, | ||
}); | ||
} | ||
} | ||
pkg['ember-addon'] = Object.assign({}, pkg['ember-addon'], { | ||
'app-js': appJS, | ||
}); | ||
writeJsonSync('package.json', pkg, { spaces: 2 }); | ||
}, | ||
}; | ||
} |
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,23 @@ | ||
import { createFilter } from '@rollup/pluginutils'; | ||
import type { Plugin } from 'rollup'; | ||
import { readFileSync } from 'fs'; | ||
const backtick = '`'; | ||
|
||
export default function rollupHbsPlugin(): Plugin { | ||
const filter = createFilter('**/*.hbs'); | ||
|
||
return { | ||
name: 'rollup-hbs-plugin', | ||
load(id: string) { | ||
if (!filter(id)) return; | ||
let input = readFileSync(id, 'utf8'); | ||
let code = | ||
`import { hbs } from 'ember-cli-htmlbars';\n` + | ||
`export default hbs${backtick}${input}${backtick};`; | ||
return { | ||
code, | ||
id: id + '.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,48 @@ | ||
import walkSync from 'walk-sync'; | ||
import type { Plugin } from 'rollup'; | ||
import { readFileSync } from 'fs'; | ||
import { join } from 'path'; | ||
import minimatch from 'minimatch'; | ||
|
||
export default function keepAssets({ | ||
from, | ||
include, | ||
}: { | ||
from: string; | ||
include: string[]; | ||
}): Plugin { | ||
return { | ||
name: 'copy-assets', | ||
|
||
// imports of assets should be left alone in the source code. This can cover | ||
// the case of .css as defined in the embroider v2 addon spec. | ||
async resolveId(source, importer, options) { | ||
const resolution = await this.resolve(source, importer, { | ||
skipSelf: true, | ||
...options, | ||
}); | ||
if ( | ||
resolution && | ||
include.some((pattern) => minimatch(resolution.id, pattern)) | ||
) { | ||
return { id: source, external: true }; | ||
} | ||
return resolution; | ||
}, | ||
|
||
// the assets go into the output directory in the same relative locations as | ||
// in the input directory | ||
async generateBundle() { | ||
for (let name of walkSync(from, { | ||
globs: include, | ||
directories: false, | ||
})) { | ||
this.emitFile({ | ||
type: 'asset', | ||
fileName: name, | ||
source: readFileSync(join(from, name), 'utf8'), | ||
}); | ||
} | ||
}, | ||
}; | ||
} |
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,23 @@ | ||
import walkSync from 'walk-sync'; | ||
import type { Plugin } from 'rollup'; | ||
import { join } from 'path'; | ||
|
||
export default function publicEntrypoints(args: { | ||
srcDir: string; | ||
include: string[]; | ||
}): Plugin { | ||
return { | ||
name: 'addon-modules', | ||
buildStart() { | ||
for (let name of walkSync(args.srcDir, { | ||
globs: args.include, | ||
})) { | ||
this.emitFile({ | ||
type: 'chunk', | ||
id: join(args.srcDir, name), | ||
fileName: name, | ||
}); | ||
} | ||
}, | ||
}; | ||
} |
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,66 @@ | ||
import { default as hbs } from './rollup-hbs-plugin'; | ||
import { default as publicEntrypoints } from './rollup-public-entrypoints'; | ||
import { default as appReexports } from './rollup-app-reexports'; | ||
import { default as clean } from 'rollup-plugin-delete'; | ||
import { default as keepAssets } from './rollup-keep-assets'; | ||
import type { Plugin } from 'rollup'; | ||
|
||
export class Addon { | ||
#srcDir: string; | ||
#destDir: string; | ||
|
||
constructor(params: { srcDir?: string; destDir?: string } = {}) { | ||
this.#srcDir = params.srcDir ?? 'src'; | ||
this.#destDir = params.destDir ?? 'dist'; | ||
} | ||
|
||
// Given a list of globs describing modules in your srcDir, this generates | ||
// corresponding appTree modules that contain reexports, and updates your | ||
// package.json metadata to list them all. | ||
appReexports(patterns: string[]): Plugin { | ||
return appReexports({ | ||
from: this.#srcDir, | ||
to: this.#destDir, | ||
include: patterns, | ||
}); | ||
} | ||
|
||
// This configures rollup to emit public entrypoints for each module in your | ||
// srcDir that matches one of the given globs. Typical addons will want to | ||
// match patterns like "components/**/*.js", "index.js", and "test-support.js". | ||
publicEntrypoints(patterns: string[]) { | ||
return publicEntrypoints({ srcDir: this.#srcDir, include: patterns }); | ||
} | ||
|
||
// This wraps standalone .hbs files as Javascript files using inline | ||
// templates. This means special resolving rules for .hbs files aren't | ||
// required for javascript tooling to understand your package. | ||
hbs() { | ||
return hbs(); | ||
} | ||
|
||
// By default rollup does not clear the output directory between builds. This | ||
// does that. | ||
clean() { | ||
return clean({ targets: `${this.#destDir}/*` }); | ||
} | ||
|
||
// V2 Addons are allowed to contain imports of .css files. This tells rollup | ||
// to leave those imports alone and to make sure the corresponding .css files | ||
// are kept in the same relative locations in the destDir as they were in the | ||
// srcDir. | ||
keepAssets(patterns: string[]) { | ||
return keepAssets({ | ||
from: this.#srcDir, | ||
include: patterns, | ||
}); | ||
} | ||
|
||
// This is the default `output` configuration you should pass to rollup. We're | ||
// emitting ES modules, in your `destDir`, and their filenames are equal to | ||
// their bundle names (the bundle names get generated by `publicEntrypoints` | ||
// above). | ||
output() { | ||
return { dir: this.#destDir, format: 'es', entryFileNames: '[name]' }; | ||
} | ||
} |
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,4 @@ | ||
export { | ||
default, | ||
Options, | ||
} from '@embroider/shared-internals/src/template-colocation-plugin'; |
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
Oops, something went wrong.