diff --git a/README.md b/README.md
index 9c338e6..b044d22 100644
--- a/README.md
+++ b/README.md
@@ -24,6 +24,7 @@ This repo includes the following presets and plugins:
- [babel-preset-vite](./packages/babel-preset-vite)
- [babel-plugin-transform-vite-meta-env](./packages/babel-plugin-transform-vite-meta-env)
- [babel-plugin-transform-vite-meta-glob](./packages/babel-plugin-transform-vite-meta-glob)
+ - [babel-plugin-transform-vite-meta-hot](./packages/babel-plugin-transform-vite-meta-hot)
For installation, usage and example, please refer to the documentation in the above packages.
@@ -41,6 +42,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
Mohit 💻 |
Rubén Moya 💻 |
Mitchel van Bever 🤔 |
+ Kelvin Zhang 💻⚠️ 📖 |
diff --git a/package.json b/package.json
index 40dd7d9..542a080 100644
--- a/package.json
+++ b/package.json
@@ -48,10 +48,12 @@
"build": "run-p --aggregate-output build:**",
"build:babel-plugin-transform-vite-meta-env": "npm run build --prefix packages/babel-plugin-transform-vite-meta-env",
"build:babel-plugin-transform-vite-meta-glob": "npm run build --prefix packages/babel-plugin-transform-vite-meta-glob",
+ "build:babel-plugin-transform-vite-meta-hot": "npm run build --prefix packages/babel-plugin-transform-vite-meta-hot",
"build:babel-preset-vite": "npm run build --prefix packages/babel-preset-vite",
"test": "run-p --aggregate-output test:** --",
"test:babel-plugin-transform-vite-meta-env": "npm run test --prefix packages/babel-plugin-transform-vite-meta-env -- --coverage",
"test:babel-plugin-transform-vite-meta-glob": "npm run test --prefix packages/babel-plugin-transform-vite-meta-glob -- --coverage",
+ "test:babel-plugin-transform-vite-meta-hot": "npm run test --prefix packages/babel-plugin-transform-vite-meta-hot -- --coverage",
"test:babel-preset-vite": "npm run test --prefix packages/babel-preset-vite -- --coverage",
"typecheck": "kcd-scripts typecheck",
"lint": "kcd-scripts lint",
diff --git a/packages/babel-plugin-transform-vite-meta-hot/.npmrc b/packages/babel-plugin-transform-vite-meta-hot/.npmrc
new file mode 100644
index 0000000..4fd15ed
--- /dev/null
+++ b/packages/babel-plugin-transform-vite-meta-hot/.npmrc
@@ -0,0 +1,2 @@
+package-lock=false
+legacy-peer-deps=true
diff --git a/packages/babel-plugin-transform-vite-meta-hot/LICENSE.md b/packages/babel-plugin-transform-vite-meta-hot/LICENSE.md
new file mode 100644
index 0000000..7f4e4f1
--- /dev/null
+++ b/packages/babel-plugin-transform-vite-meta-hot/LICENSE.md
@@ -0,0 +1,18 @@
+MIT License
+
+Copyright (c) [2021] [Michael Peyper]
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge, publish, distribute,
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
+OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/packages/babel-plugin-transform-vite-meta-hot/README.md b/packages/babel-plugin-transform-vite-meta-hot/README.md
new file mode 100644
index 0000000..77a550f
--- /dev/null
+++ b/packages/babel-plugin-transform-vite-meta-hot/README.md
@@ -0,0 +1,71 @@
+# babel-plugin-transform-vite-meta-hot
+
+
+[![Build Status](https://img.shields.io/github/workflow/status/OpenSourceRaidGuild/babel-vite/validate?logo=github&style=flat-square)](https://github.com/OpenSourceRaidGuild/babel-vite/actions?query=workflow%3Avalidate)
+[![codecov](https://img.shields.io/codecov/c/github/OpenSourceRaidGuild/babel-vite.svg?style=flat-square)](https://codecov.io/gh/OpenSourceRaidGuild/babel-vite)
+[![version](https://img.shields.io/npm/v/babel-plugin-transform-vite-meta-hot.svg?style=flat-square)](https://www.npmjs.com/package/babel-plugin-transform-vite-meta-hot)
+[![downloads](https://img.shields.io/npm/dm/babel-plugin-transform-vite-meta-hot.svg?style=flat-square)](http://www.npmtrends.com/babel-plugin-transform-vite-meta-hot)
+[![MIT License](https://img.shields.io/npm/l/babel-plugin-transform-vite-meta-hot.svg?style=flat-square)](https://github.com/OpenSourceRaidGuild/babel-vite/blob/master/LICENSE.md)
+
+[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com)
+[![Code of Conduct](https://img.shields.io/badge/code%20of-conduct-ff69b4.svg?style=flat-square)](https://github.com/OpenSourceRaidGuild/babel-vite/blob/master/CODE_OF_CONDUCT.md)
+[![Discord](https://img.shields.io/discord/808364903822917662.svg?color=7389D8&labelColor=6A7EC2&logo=discord&logoColor=ffffff&style=flat-square)](https://discord.gg/grS89HWeYh)
+
+[![Watch on GitHub](https://img.shields.io/github/watchers/OpenSourceRaidGuild/babel-vite.svg?style=social)](https://github.com/OpenSourceRaidGuild/babel-vite/watchers)
+[![Star on GitHub](https://img.shields.io/github/stars/OpenSourceRaidGuild/babel-vite.svg?style=social)](https://github.com/OpenSourceRaidGuild/babel-vite/stargazers)
+[![Tweet](https://img.shields.io/twitter/url/https/github.com/OpenSourceRaidGuild/babel-vite.svg?style=social)](https://twitter.com/intent/tweet?text=Check%20out%20babel-plugin-transform-vite-meta-hot%20by%20OpenSourceRaidGuild%20https%3A%2F%2Fgithub.com%2FOpenSourceRaidGuild%2Fbabel-vite%20%F0%9F%91%8D)
+
+
+> Please note: this plugin is intended to provide an approximation of some of Vite specific
+> transformations when running the code in non-Vite environment, for example, running tests with a
+> NodeJS based test runner.
+>
+> **The functionality within these transformations should not be relied upon in production.**
+
+## Example
+
+**In**
+
+```
+if (import.meta.hot) {
+ import.meta.hot.accept(callback);
+}
+```
+
+**Out**
+
+```
+if (module.hot) {
+ module.hot.accept(callback);
+}
+```
+
+## Installation
+
+```sh
+npm install --save-dev babel-plugin-transform-vite-meta-hot
+```
+
+## Usage
+
+### With a configuration file (Recommended)
+
+```json
+{
+ "plugins": ["babel-plugin-transform-vite-meta-hot"]
+}
+```
+
+### Via CLI
+
+```sh
+babel --plugins babel-plugin-transform-vite-meta-hot script.js
+```
+
+### Via Node API
+
+```javascript
+require('@babel/core').transformSync('code', {
+ plugins: ['babel-plugin-transform-vite-meta-hot']
+})
+```
diff --git a/packages/babel-plugin-transform-vite-meta-hot/package.json b/packages/babel-plugin-transform-vite-meta-hot/package.json
new file mode 100644
index 0000000..2cab9f9
--- /dev/null
+++ b/packages/babel-plugin-transform-vite-meta-hot/package.json
@@ -0,0 +1,44 @@
+{
+ "name": "babel-plugin-transform-vite-meta-hot",
+ "version": "0.0.0-semantically-released",
+ "description": "babel plugin that emulates vite's import.meta.hot functionality",
+ "main": "lib/index.js",
+ "typings": "lib/index.d.ts",
+ "files": [
+ "lib",
+ "src"
+ ],
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/OpenSourceRaidGuild/babel-vite.git"
+ },
+ "keywords": [
+ "babel",
+ "vite",
+ "plugin",
+ "import",
+ "meta",
+ "hot"
+ ],
+ "author": "Kelvin Zhang ",
+ "license": "MIT",
+ "bugs": {
+ "url": "https://github.com/OpenSourceRaidGuild/babel-vite/issues"
+ },
+ "homepage": "https://github.com/OpenSourceRaidGuild/babel-vite#readme",
+ "scripts": {
+ "build": "kcd-scripts build --out-dir lib",
+ "test": "kcd-scripts test"
+ },
+ "devDependencies": {
+ "@babel/core": "^7.13.8",
+ "@types/babel-plugin-tester": "^9.0.1",
+ "babel-plugin-tester": "^10.0.0",
+ "kcd-scripts": "^12.0.0",
+ "typescript": "^4.2.2"
+ },
+ "dependencies": {
+ "@babel/runtime": "^7.13.9",
+ "@types/babel__core": "^7.1.12"
+ }
+}
diff --git a/packages/babel-plugin-transform-vite-meta-hot/src/__tests__/__snapshots__/index.ts.snap b/packages/babel-plugin-transform-vite-meta-hot/src/__tests__/__snapshots__/index.ts.snap
new file mode 100644
index 0000000..cb43cfe
--- /dev/null
+++ b/packages/babel-plugin-transform-vite-meta-hot/src/__tests__/__snapshots__/index.ts.snap
@@ -0,0 +1,91 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`vite-meta-hot not import.meta lookup: not import.meta lookup 1`] = `
+
+const x = import.meta()
+
+ ↓ ↓ ↓ ↓ ↓ ↓
+
+const x = import.meta()
+
+
+`;
+
+exports[`vite-meta-hot not replace import.meta.hot: not replace import.meta.hot 1`] = `
+
+const x = module.hot
+
+ ↓ ↓ ↓ ↓ ↓ ↓
+
+const x = module.hot
+
+
+`;
+
+exports[`vite-meta-hot not replace key access: not replace key access 1`] = `
+
+const key = "env"; const x = import.meta[key]
+
+ ↓ ↓ ↓ ↓ ↓ ↓
+
+const key = 'env'
+const x = import.meta[key]
+
+
+`;
+
+exports[`vite-meta-hot not replace string access: not replace string access 1`] = `
+
+const x = import.meta["env"]
+
+ ↓ ↓ ↓ ↓ ↓ ↓
+
+const x = import.meta['env']
+
+
+`;
+
+exports[`vite-meta-hot not replaceable: not replaceable 1`] = `
+
+const x = import.meta.other
+
+ ↓ ↓ ↓ ↓ ↓ ↓
+
+const x = import.meta.other
+
+
+`;
+
+exports[`vite-meta-hot replace import.meta.hot: replace import.meta.hot 1`] = `
+
+const x = import.meta.hot
+
+ ↓ ↓ ↓ ↓ ↓ ↓
+
+const x = module.hot
+
+
+`;
+
+exports[`vite-meta-hot replace key access: replace key access 1`] = `
+
+const key = "hot"; const x = import.meta[key]
+
+ ↓ ↓ ↓ ↓ ↓ ↓
+
+const key = 'hot'
+const x = module.hot
+
+
+`;
+
+exports[`vite-meta-hot replace string access: replace string access 1`] = `
+
+const x = import.meta["hot"]
+
+ ↓ ↓ ↓ ↓ ↓ ↓
+
+const x = module.hot
+
+
+`;
diff --git a/packages/babel-plugin-transform-vite-meta-hot/src/__tests__/index.ts b/packages/babel-plugin-transform-vite-meta-hot/src/__tests__/index.ts
new file mode 100644
index 0000000..75163b1
--- /dev/null
+++ b/packages/babel-plugin-transform-vite-meta-hot/src/__tests__/index.ts
@@ -0,0 +1,18 @@
+import pluginTester from 'babel-plugin-tester'
+import plugin from '..'
+
+pluginTester({
+ plugin,
+ pluginName: 'vite-meta-hot',
+ snapshot: true,
+ tests: {
+ 'replace import.meta.hot': 'const x = import.meta.hot',
+ 'not replace import.meta.hot': 'const x = module.hot',
+ 'replace string access': 'const x = import.meta["hot"]',
+ 'not replace string access': 'const x = import.meta["env"]',
+ 'replace key access': 'const key = "hot"; const x = import.meta[key]',
+ 'not replace key access': 'const key = "env"; const x = import.meta[key]',
+ 'not replaceable': 'const x = import.meta.other',
+ 'not import.meta lookup': 'const x = import.meta()'
+ }
+})
diff --git a/packages/babel-plugin-transform-vite-meta-hot/src/index.ts b/packages/babel-plugin-transform-vite-meta-hot/src/index.ts
new file mode 100644
index 0000000..1853018
--- /dev/null
+++ b/packages/babel-plugin-transform-vite-meta-hot/src/index.ts
@@ -0,0 +1,52 @@
+import type babelCore from '@babel/core'
+
+export default function viteMetaHotBabelPlugin({
+ template,
+ types: t
+}: typeof babelCore): babelCore.PluginObj {
+ return {
+ name: 'vite-meta-hot',
+ visitor: {
+ MemberExpression(path) {
+ const isMetaProperty = t.isMetaProperty(path.node.object)
+ const isHotVar = t.isIdentifier(path.node.property) && path.node.property.name === 'hot'
+
+ if (!isMetaProperty || !isHotVar) {
+ return
+ }
+
+ path.replaceWith(template.expression.ast('module.hot'))
+ },
+ StringLiteral(path) {
+ const isMetaProperty =
+ t.isMemberExpression(path.parentPath.node) &&
+ t.isMetaProperty(path.parentPath.node.object)
+ const isHotVar = path.node.value === 'hot'
+
+ if (!isMetaProperty || !isHotVar) {
+ return
+ }
+
+ path.parentPath.replaceWith(template.expression.ast('module.hot'))
+ },
+ Identifier(path) {
+ if (
+ !t.isMemberExpression(path.parentPath.node) ||
+ !t.isMetaProperty(path.parentPath.node.object)
+ ) {
+ return
+ }
+
+ const key = path.node.name
+ /* @ts-expect-error outdated types */
+ // eslint-disable-next-line
+ const keyValue = path.scope.getBinding(key)?.path.node.init?.value
+ if (keyValue !== 'hot') {
+ return
+ }
+
+ path.parentPath.replaceWith(template.expression.ast('module.hot'))
+ }
+ }
+ }
+}
diff --git a/packages/babel-plugin-transform-vite-meta-hot/tsconfig.json b/packages/babel-plugin-transform-vite-meta-hot/tsconfig.json
new file mode 100644
index 0000000..52d43ea
--- /dev/null
+++ b/packages/babel-plugin-transform-vite-meta-hot/tsconfig.json
@@ -0,0 +1,4 @@
+{
+ "extends": "../../tsconfig.json",
+ "include": ["src/**/*"]
+}
diff --git a/packages/babel-preset-vite/README.md b/packages/babel-preset-vite/README.md
index 36a4a4b..dfe4f8b 100644
--- a/packages/babel-preset-vite/README.md
+++ b/packages/babel-preset-vite/README.md
@@ -26,6 +26,7 @@ This preset includes the following plugins:
- [babel-plugin-transform-vite-meta-env](../babel-plugin-transform-vite-meta-env)
- [babel-plugin-transform-vite-meta-glob](../babel-plugin-transform-vite-meta-glob)
+- [babel-plugin-transform-vite-meta-hot](../babel-plugin-transform-vite-meta-hot)
## Installation
@@ -54,7 +55,8 @@ With options:
"babel-preset-vite",
{
"env": false, // defaults to true
- "glob": false // defaults to true
+ "glob": false, // defaults to true
+ "hot": false // defaults to true
}
]
]
@@ -92,5 +94,12 @@ Toggles whether or not to perform
[`import.meta.glob` and `import.meta.globEager`](https://vitejs.dev/guide/features.html#glob-import)
transformations.
+### `hot`
+
+`boolean`, defaults to `true`
+
+Toggles whether or not to perform [`import.meta.hot`](https://vitejs.dev/guide/api-hmr.html)
+transformations.
+
> You can read more about configuring preset options
> [here](https://babeljs.io/docs/en/presets#preset-options)
diff --git a/packages/babel-preset-vite/package.json b/packages/babel-preset-vite/package.json
index ce08d67..9b7f28f 100644
--- a/packages/babel-preset-vite/package.json
+++ b/packages/babel-preset-vite/package.json
@@ -15,7 +15,10 @@
"keywords": [
"babel",
"vite",
- "preset"
+ "preset",
+ "env",
+ "glob",
+ "hot"
],
"author": "Michael Peyper ",
"license": "MIT",
@@ -38,6 +41,7 @@
"@babel/runtime": "^7.13.9",
"@types/babel__core": "^7.1.12",
"babel-plugin-transform-vite-meta-env": "^0.0.0-semantically-released",
- "babel-plugin-transform-vite-meta-glob": "^0.0.0-semantically-released"
+ "babel-plugin-transform-vite-meta-glob": "^0.0.0-semantically-released",
+ "babel-plugin-transform-vite-meta-hot": "^0.0.0-semantically-released"
}
}
diff --git a/packages/babel-preset-vite/src/__tests__/__snapshots__/index.ts.snap b/packages/babel-preset-vite/src/__tests__/__snapshots__/index.ts.snap
index e987bac..2960b10 100644
--- a/packages/babel-preset-vite/src/__tests__/__snapshots__/index.ts.snap
+++ b/packages/babel-preset-vite/src/__tests__/__snapshots__/index.ts.snap
@@ -8,6 +8,8 @@ export const modules = import.meta.glob('files/*.ts')
export const eagerModules = import.meta.globEager('files/*.ts')
+export const hot = import.meta.hot
+
↓ ↓ ↓ ↓ ↓ ↓
export const envVar = process.env.VITE_VAR
@@ -17,6 +19,7 @@ export const modules = {
export const eagerModules = {
'files/file1.ts': require('files/file1.ts')
}
+export const hot = module.hot
`;
@@ -29,6 +32,8 @@ export const modules = import.meta.glob('files/*.ts')
export const eagerModules = import.meta.globEager('files/*.ts')
+export const hot = import.meta.hot
+
↓ ↓ ↓ ↓ ↓ ↓
export const envVar = process.env.VITE_VAR
@@ -38,6 +43,7 @@ export const modules = {
export const eagerModules = {
'files/file1.ts': require('files/file1.ts')
}
+export const hot = module.hot
`;
@@ -50,11 +56,14 @@ export const modules = import.meta.glob('files/*.ts')
export const eagerModules = import.meta.globEager('files/*.ts')
+export const hot = import.meta.hot
+
↓ ↓ ↓ ↓ ↓ ↓
export const envVar = process.env.VITE_VAR
export const modules = import.meta.glob('files/*.ts')
export const eagerModules = import.meta.globEager('files/*.ts')
+export const hot = import.meta.hot
`;
@@ -67,6 +76,8 @@ export const modules = import.meta.glob('files/*.ts')
export const eagerModules = import.meta.globEager('files/*.ts')
+export const hot = import.meta.hot
+
↓ ↓ ↓ ↓ ↓ ↓
export const envVar = import.meta.env.VITE_VAR
@@ -76,6 +87,27 @@ export const modules = {
export const eagerModules = {
'files/file1.ts': require('files/file1.ts')
}
+export const hot = import.meta.hot
+
+
+`;
+
+exports[`vite hot-only: hot-only 1`] = `
+
+export const envVar = import.meta.env.VITE_VAR
+
+export const modules = import.meta.glob('files/*.ts')
+
+export const eagerModules = import.meta.globEager('files/*.ts')
+
+export const hot = import.meta.hot
+
+ ↓ ↓ ↓ ↓ ↓ ↓
+
+export const envVar = import.meta.env.VITE_VAR
+export const modules = import.meta.glob('files/*.ts')
+export const eagerModules = import.meta.globEager('files/*.ts')
+export const hot = module.hot
`;
diff --git a/packages/babel-preset-vite/src/__tests__/fixtures/input.ts b/packages/babel-preset-vite/src/__tests__/fixtures/input.ts
index c65d5b8..d2d2a5f 100644
--- a/packages/babel-preset-vite/src/__tests__/fixtures/input.ts
+++ b/packages/babel-preset-vite/src/__tests__/fixtures/input.ts
@@ -3,3 +3,5 @@ export const envVar = import.meta.env.VITE_VAR
export const modules = import.meta.glob('files/*.ts')
export const eagerModules = import.meta.globEager('files/*.ts')
+
+export const hot = import.meta.hot
diff --git a/packages/babel-preset-vite/src/__tests__/index.ts b/packages/babel-preset-vite/src/__tests__/index.ts
index 04b81a4..43ce10e 100644
--- a/packages/babel-preset-vite/src/__tests__/index.ts
+++ b/packages/babel-preset-vite/src/__tests__/index.ts
@@ -15,8 +15,9 @@ pluginTester({
babelOptions: { filename: __filename },
tests: {
defaults: fixture('input'),
- all: fixture('input', { env: true, glob: true }),
- 'env-only': fixture('input', { env: true, glob: false }),
- 'glob-only': fixture('input', { env: false, glob: true })
+ all: fixture('input', { env: true, glob: true, hot: true }),
+ 'env-only': fixture('input', { env: true, glob: false, hot: false }),
+ 'glob-only': fixture('input', { env: false, glob: true, hot: false }),
+ 'hot-only': fixture('input', { env: false, glob: false, hot: true })
}
})
diff --git a/packages/babel-preset-vite/src/index.ts b/packages/babel-preset-vite/src/index.ts
index 7937f9a..9f87e36 100644
--- a/packages/babel-preset-vite/src/index.ts
+++ b/packages/babel-preset-vite/src/index.ts
@@ -3,17 +3,19 @@ import type babelCore from '@babel/core'
export interface VitePresetOptions {
env?: boolean
glob?: boolean
+ hot?: boolean
}
function vitePreset(
_: typeof babelCore,
opts: VitePresetOptions
): { plugins: babelCore.PluginItem[] } {
- const { env = true, glob = true } = opts
+ const { env = true, glob = true, hot = true } = opts
return {
plugins: [
glob && require.resolve('babel-plugin-transform-vite-meta-glob'),
- env && require.resolve('babel-plugin-transform-vite-meta-env')
+ env && require.resolve('babel-plugin-transform-vite-meta-env'),
+ hot && require.resolve('babel-plugin-transform-vite-meta-hot')
].filter(isEnabled)
}
}