Skip to content

Commit d6aae1a

Browse files
committed
Core: Provide a package.json exports setup inspired by jQuery Core
The Migrate setup is simpler than Core as it doesn't have the slim or factory versions, but the core ideas are similar. Fixes gh-524 Ref jquery/jquery#5255 Ref jquery/jquery#5429
1 parent 868e11d commit d6aae1a

26 files changed

+1635
-59
lines changed

.github/workflows/browser-tests.yml

+1-4
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,7 @@ jobs:
4343
run: npm install
4444

4545
- name: Run tests
46-
run: |
47-
npm run pretest
48-
npm run test:unit -- -c jtr-local.yml \
49-
--headless -b ${{ matrix.BROWSER }} -f plugin=${{ matrix.MIGRATE_VERSION }}
46+
run: npm run test:browser -- -f plugin=${{ matrix.MIGRATE_VERSION }}
5047

5148
ie:
5249
runs-on: windows-latest

.github/workflows/browserstack.yml

+3
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ jobs:
5858
- name: Install dependencies
5959
run: npm install
6060

61+
- name: Build jQuery
62+
run: npm run build:all
63+
6164
- name: Pretest script
6265
run: npm run pretest
6366

.github/workflows/node.js.yml

+18-11
Original file line numberDiff line numberDiff line change
@@ -5,32 +5,39 @@ on:
55
push:
66
branches-ignore: "dependabot/**"
77

8-
env:
9-
NODE_VERSION: 22.x
10-
118
jobs:
12-
node-smoke-test:
9+
build-and-test:
1310
runs-on: ubuntu-latest
14-
name: Node smoke tests
11+
name: ${{ matrix.NPM_SCRIPT }} - ${{ matrix.NAME }} (${{ matrix.NODE_VERSION }})
12+
strategy:
13+
fail-fast: false
14+
matrix:
15+
NAME: ["Node"]
16+
NODE_VERSION: [18.x, 20.x, 22.x, 23.x]
17+
NPM_SCRIPT: ["test:browserless"]
18+
include:
19+
- NAME: "Node"
20+
NODE_VERSION: "22.x"
21+
NPM_SCRIPT: "lint"
1522
steps:
1623
- name: Checkout
1724
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
1825

19-
- name: Use Node.js ${{ env.NODE_VERSION }}
26+
- name: Use Node.js ${{ matrix.NODE_VERSION }}
2027
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
2128
with:
22-
node-version: ${{ env.NODE_VERSION }}
29+
node-version: ${{ matrix.NODE_VERSION }}
2330

2431
- name: Cache
2532
uses: actions/cache@d4323d4df104b026a6aa633fdb11d772146be0bf # v4.2.2
2633
with:
2734
path: ~/.npm
28-
key: ${{ runner.os }}-node-${{ env.NODE_VERSION }}-npm-lock-${{ hashFiles('**/package-lock.json') }}
35+
key: ${{ runner.os }}-node-${{ matrix.NODE_VERSION }}-npm-lock-${{ hashFiles('**/package-lock.json') }}
2936
restore-keys: |
30-
${{ runner.os }}-node-${{ env.NODE_VERSION }}-npm-lock-
37+
${{ runner.os }}-node-${{ matrix.NODE_VERSION }}-npm-lock-
3138
3239
- name: Install dependencies
3340
run: npm install
3441

35-
- name: Run Node smoke tests
36-
run: npm run test:node_smoke_tests
42+
- name: Run tests
43+
run: npm run ${{ matrix.NPM_SCRIPT }}

.gitignore

+8-1
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,16 @@ CDN
1111
.eslintcache
1212

1313
# Ignore built files in `dist` folder
14-
# Leave package.json
14+
# Leave the package.json and wrappers
1515
/dist/*
1616
!/dist/package.json
17+
!/dist/wrappers
18+
19+
# Ignore built files in `dist-module` folder
20+
# Leave the package.json and wrappers
21+
/dist-module/*
22+
!/dist-module/package.json
23+
!/dist-module/wrappers
1724

1825
/external
1926
/node_modules

build/command.js

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import yargs from "yargs/yargs";
2+
import { build } from "./tasks/build.js";
3+
4+
const argv = yargs( process.argv.slice( 2 ) )
5+
.version( false )
6+
.command( {
7+
command: "[options]",
8+
describe: "Build a jQuery Migrate bundle"
9+
} )
10+
.option( "filename", {
11+
alias: "f",
12+
type: "string",
13+
description:
14+
"Set the filename of the built file. Defaults to jquery.js."
15+
} )
16+
.option( "dir", {
17+
alias: "d",
18+
type: "string",
19+
description:
20+
"Set the dir to which to output the built file. Defaults to /dist."
21+
} )
22+
.option( "version", {
23+
alias: "v",
24+
type: "string",
25+
description:
26+
"Set the version to include in the built file. " +
27+
"Defaults to the version in package.json plus the " +
28+
"short commit SHA and any excluded modules."
29+
} )
30+
.option( "watch", {
31+
alias: "w",
32+
type: "boolean",
33+
description:
34+
"Watch the source files and rebuild when they change."
35+
} )
36+
.option( "esm", {
37+
type: "boolean",
38+
description:
39+
"Build an ES module (ESM) bundle. " +
40+
"By default, a UMD bundle is built."
41+
} )
42+
.help()
43+
.argv;
44+
45+
build( argv );

build/tasks/build-default.js

-3
This file was deleted.

build/tasks/build-watch.js

-3
This file was deleted.

build/tasks/build.js

+54-19
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,33 @@ async function readJSON( filename ) {
2222
return JSON.parse( await read( filename ) );
2323
}
2424

25+
async function getOutputRollupOptions( {
26+
esm = false
27+
} = {} ) {
28+
const wrapperFilePath = path.join( "src", `wrapper${
29+
esm ? "-esm" : ""
30+
}.js` );
31+
32+
const wrapperSource = await read( wrapperFilePath );
33+
34+
// Catch `// @CODE` and subsequent comment lines event if they don't start
35+
// in the first column.
36+
const wrapper = wrapperSource.split(
37+
/[\x20\t]*\/\/ @CODE\n(?:[\x20\t]*\/\/[^\n]+\n)*/
38+
);
39+
40+
return {
41+
42+
// The ESM format is not actually used as we strip it during the
43+
// build, inserting our own wrappers; it's just that it doesn't
44+
// generate any extra wrappers so there's nothing for us to remove.
45+
format: "esm",
46+
47+
intro: wrapper[ 0 ].replace( /\n*$/, "" ),
48+
outro: wrapper[ 1 ].replace( /^\n*/, "" )
49+
};
50+
}
51+
2552
async function writeCompiled( { code, dir, filename, version } ) {
2653
const compiledContents = code
2754

@@ -34,12 +61,12 @@ async function writeCompiled( { code, dir, filename, version } ) {
3461

3562
await writeFile( path.join( dir, filename ), compiledContents );
3663
console.log( `[${ getTimestamp() }] ${ filename } v${ version } created.` );
37-
await minify( { dir, filename, version } );
3864
}
3965

4066
export async function build( {
4167
dir = "dist",
4268
filename = "jquery-migrate.js",
69+
esm = false,
4370
watch = false,
4471
version
4572
} = {} ) {
@@ -59,24 +86,8 @@ export async function build( {
5986
}`;
6087
}
6188

62-
// Catch `// @CODE` and subsequent comment lines event if they don't start
63-
// in the first column.
64-
const wrapperSrc = await read( "src/wrapper.js" );
65-
const wrapper = wrapperSrc.split(
66-
/[\x20\t]*\/\/ @CODE\n(?:[\x20\t]*\/\/[^\n]+\n)*/
67-
);
68-
6989
const inputRollupOptions = {};
70-
const outputRollupOptions = {
71-
72-
// The ESM format is not actually used as we strip it during
73-
// the build; it's just that it doesn't generate any extra
74-
// wrappers so there's nothing for us to remove.
75-
format: "esm",
76-
77-
intro: wrapper[ 0 ].replace( /\n*$/, "" ),
78-
outro: wrapper[ 1 ].replace( /^\n*/, "" )
79-
};
90+
const outputRollupOptions = await getOutputRollupOptions( { esm } );
8091
const src = "src/migrate.js";
8192

8293
inputRollupOptions.input = path.resolve( src );
@@ -122,9 +133,33 @@ export async function build( {
122133
} = await bundle.generate( outputRollupOptions );
123134

124135
await writeCompiled( { code, dir, filename, version } );
136+
await minify( { dir, filename, version } );
137+
}
138+
}
125139

140+
export async function buildDefaultFiles( {
141+
version = process.env.VERSION,
142+
watch
143+
} = {} ) {
144+
await Promise.all( [
145+
build( { version, watch } ),
146+
build( {
147+
dir: "dist-module",
148+
filename: "jquery-migrate.module.js",
149+
esm: true,
150+
version,
151+
watch
152+
} )
153+
] );
154+
155+
if ( watch ) {
156+
console.log( "Watching files..." );
157+
} else {
126158
return compareSize( {
127-
files: [ "dist/jquery-migrate.min.js" ]
159+
files: [
160+
"dist/jquery-migrate.min.js",
161+
"dist-module/jquery-migrate.module.min.js"
162+
]
128163
} );
129164
}
130165
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// Node.js is able to import from a CommonJS module in an ESM one.
2+
import jQuery from "../../dist/jquery-migrate.js";
3+
4+
export { jQuery, jQuery as $ };
5+
export default jQuery;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
"use strict";
2+
3+
// Bundlers are able to synchronously require an ESM module from a CommonJS one.
4+
const { jQuery } = require( "../../dist-module/jquery-migrate.module.js" );
5+
module.exports = jQuery;

eslint.config.js

+51-3
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,13 @@ export default [
1212
},
1313

1414
{
15-
files: [ "eslint.config.js", "build/**" ],
15+
files: [
16+
"eslint.config.js",
17+
".release-it.cjs",
18+
"build/**",
19+
"test/node_smoke_tests/**",
20+
"test/bundler_smoke_tests/**/*"
21+
],
1622
languageOptions: {
1723
ecmaVersion: "latest",
1824
globals: {
@@ -60,18 +66,44 @@ export default [
6066
}
6167
},
6268

69+
{
70+
files: [
71+
"src/wrapper.js",
72+
"src/wrapper-esm.js",
73+
"src/wrapper-factory.js",
74+
"src/wrapper-factory-esm.js"
75+
],
76+
languageOptions: {
77+
globals: {
78+
jQuery: false
79+
}
80+
},
81+
rules: {
82+
"no-unused-vars": "off",
83+
indent: [
84+
"error",
85+
"tab",
86+
{
87+
88+
// This makes it so code within the wrapper is not indented.
89+
ignoredNodes: [
90+
"Program > FunctionDeclaration > *"
91+
]
92+
}
93+
]
94+
}
95+
},
96+
6397
{
6498
files: [ "src/wrapper.js" ],
6599
languageOptions: {
66100
sourceType: "script",
67101
globals: {
68-
jQuery: false,
69102
define: false,
70103
module: false
71104
}
72105
},
73106
rules: {
74-
"no-unused-vars": "off",
75107
indent: [
76108
"error",
77109
"tab",
@@ -203,5 +235,21 @@ export default [
203235
ecmaVersion: 5,
204236
sourceType: "script"
205237
}
238+
},
239+
240+
{
241+
files: [ "dist-module/**" ],
242+
languageOptions: {
243+
ecmaVersion: 2015,
244+
sourceType: "module"
245+
}
246+
},
247+
248+
{
249+
files: [ "dist/wrappers/*.js" ],
250+
languageOptions: {
251+
ecmaVersion: 2015,
252+
sourceType: "commonjs"
253+
}
206254
}
207255
];

0 commit comments

Comments
 (0)