Skip to content

Commit

Permalink
Build: Add exports to package.json, export slim & esm builds
Browse files Browse the repository at this point in the history
Summary of the changes:
* define the `exports` field in `package.json`; `jQuery` & `$` are also
  exported as named exports in ESM builds now
* declare `"type": "module"` globally except for the `build` folder
* add the `--esm` option to `grunt custom`, generating jQuery as an ECMAScript
  module into the `dist-module` folder
* expand `node_smoke_tests` to test the slim & ESM builds and their various
  combinations; also, test both jQuery loaded via a path to the file as well
  as from module specifiers that should be parsed via the `exports` feature
* add details about ESM usage to the release package README
* run `compare_size` on all built minified files; don't run it anymore on
  unminified files where they don't provide lots of value
* remove the remove_map_comment task; SWC doesn't insert the
`//# sourceMappingURL=` pragma by default so there's nothing to strip

Fixes gh-4592
Closes gh-5255
  • Loading branch information
mgol committed Jul 10, 2023
1 parent 65b8503 commit 8be4c0e
Show file tree
Hide file tree
Showing 52 changed files with 887 additions and 308 deletions.
7 changes: 7 additions & 0 deletions .eslintignore
Expand Up @@ -4,6 +4,13 @@ node_modules
dist/**
!dist/jquery.js
!dist/jquery.min.js
!dist/jquery.slim.js
!dist/jquery.slim.min.js
dist-module/**
!dist-module/jquery.module.js
!dist-module/jquery.module.min.js
!dist-module/jquery.slim.module.js
!dist-module/jquery.slim.module.min.js
test/data/jquery-1.9.1.js
test/data/badcall.js
test/data/badjson.js
Expand Down
11 changes: 10 additions & 1 deletion .gitignore
Expand Up @@ -12,9 +12,18 @@ package-lock.json

npm-debug.log*

# Ignore everything in dist folder except for eslint config
# Ignore everything in `dist` folder except for the ESLint config
/dist/*
!/dist/.eslintrc.json
!/dist/package.json

# Ignore everything in the `dist-module` folder except for the ESLint config,
# package.json & Node module wrapper files
/dist-module/*
!/dist-module/.eslintrc.json
!/dist-module/package.json
!/dist-module/jquery.node-module-wrapper.js
!/dist-module/jquery.node-module-wrapper.slim.js

/external
/node_modules
Expand Down
2 changes: 1 addition & 1 deletion .npmignore
Expand Up @@ -9,4 +9,4 @@
/external
/speed
/test
/Gruntfile.js
/Gruntfile.cjs
78 changes: 54 additions & 24 deletions Gruntfile.js → Gruntfile.cjs
Expand Up @@ -13,19 +13,19 @@ module.exports = function( grunt ) {
}

const fs = require( "fs" );
const { spawn } = require( "child_process" );
const gzip = require( "gzip-js" );
const nodeV14OrNewer = !/^v1[0-3]\./.test( process.version );
const nodeV16OrNewer = !/^v1[0-5]\./.test( process.version );
const nodeV17OrNewer = !/^v1[0-6]\./.test( process.version );
const customBrowsers = process.env.BROWSERS && process.env.BROWSERS.split( "," );

// Support: Node.js <14
// Skip running tasks that dropped support for Node.js 10 or 12
// in this Node version.
// Support: Node.js <16
// Skip running tasks that dropped support for old Node.js in these Node versions.
function runIfNewNode( task ) {
return nodeV14OrNewer ? task : "print_old_node_message:" + task;
return nodeV16OrNewer ? task : "print_old_node_message:" + task;
}

if ( nodeV14OrNewer ) {
if ( nodeV16OrNewer ) {
const playwright = require( "playwright-webkit" );
process.env.WEBKIT_HEADLESS_BIN = playwright.webkit.executablePath();
}
Expand All @@ -34,11 +34,27 @@ module.exports = function( grunt ) {
grunt.option( "filename", "jquery.js" );
}

grunt.option( "dist-folder", grunt.option( "esm" ) ? "dist-module" : "dist" );

const builtJsFiles = [
"dist/jquery.js",
"dist/jquery.min.js",
"dist/jquery.slim.js",
"dist/jquery.slim.min.js",
"dist-module/jquery.module.js",
"dist-module/jquery.module.min.js",
"dist-module/jquery.slim.module.js",
"dist-module/jquery.slim.module.min.js"
];

const builtJsMinFiles = builtJsFiles
.filter( filepath => filepath.endsWith( ".min.js" ) );

grunt.initConfig( {
pkg: grunt.file.readJSON( "package.json" ),
dst: readOptionalJSON( "dist/.destination.json" ),
compare_size: {
files: [ "dist/jquery.js", "dist/jquery.min.js" ],
files: builtJsMinFiles,
options: {
compress: {
gz: function( contents ) {
Expand Down Expand Up @@ -122,7 +138,7 @@ module.exports = function( grunt ) {
// We have to explicitly declare "src" property otherwise "newer"
// task wouldn't work properly :/
dist: {
src: [ "dist/jquery.js", "dist/jquery.min.js" ]
src: builtJsFiles
},
dev: {
src: [
Expand All @@ -142,9 +158,10 @@ module.exports = function( grunt ) {
`!${ filePath }`
),

// Explicitly ignore `dist/` as it could be unignored by
// the above `.eslintignore` parsing.
"!dist/**/*.js"
// Explicitly ignore `dist/` & `dist-module/` as it could be unignored
// by the above `.eslintignore` parsing.
"!dist/**/*.js",
"!dist-module/**/*.js"
]
}
},
Expand Down Expand Up @@ -195,7 +212,7 @@ module.exports = function( grunt ) {
{
"middleware:mockserver": [
"factory",
require( "./test/middleware-mockserver.js" )
require( "./test/middleware-mockserver.cjs" )
]
}
],
Expand Down Expand Up @@ -319,12 +336,15 @@ module.exports = function( grunt ) {
minify: {
all: {
files: {
"dist/<%= grunt.option('filename').replace('.js', '.min.js') %>":
"dist/<%= grunt.option('filename') %>"
[ "<%= grunt.option('dist-folder') %>/" +
"<%= grunt.option('filename').replace(/\\.js$/, '.min.js') %>" ]:
"<%= grunt.option('dist-folder') %>/<%= grunt.option('filename') %>"
},
options: {
sourceMap: {
filename: "dist/<%= grunt.option('filename').replace('.js', '.min.map') %>",
filename: "<%= grunt.option('dist-folder') %>/" +
"<%= grunt.option('filename')" +
".replace(/\\.js$/, '.min.map') %>",

// The map's `files` & `sources` property are set incorrectly, fix
// them via overrides from the task config.
Expand All @@ -338,15 +358,15 @@ module.exports = function( grunt ) {
},
swc: {
format: {
ecma: 5,
ecma: grunt.option( "esm" ) ? 2015 : 5,
asciiOnly: true,
comments: false,
preamble: "/*! jQuery v4.0.0-pre | " +
"(c) OpenJS Foundation and other contributors | " +
"jquery.org/license */\n"
},
compress: {
ecma: 5,
ecma: grunt.option( "esm" ) ? 2015 : 5,
hoist_funs: false,
loops: false
},
Expand All @@ -359,7 +379,7 @@ module.exports = function( grunt ) {

// Load grunt tasks from NPM packages
require( "load-grunt-tasks" )( grunt, {
pattern: nodeV14OrNewer ? [ "grunt-*" ] : [ "grunt-*", "!grunt-eslint" ]
pattern: nodeV16OrNewer ? [ "grunt-*" ] : [ "grunt-*", "!grunt-eslint" ]
} );

// Integrate jQuery specific tasks
Expand All @@ -370,6 +390,20 @@ module.exports = function( grunt ) {
grunt.log.writeln( "Old Node.js detected, running the task \"" + task + "\" skipped..." );
} );

grunt.registerTask( "build-all-variants",
"Build all variants of the full/slim build & a script/ESM one",
function() {
const done = this.async();

spawn( "npm run build-all-variants", {
stdio: "inherit",
shell: true
} )
.on( "close", code => {
done( code === 0 );
} );
} );

grunt.registerTask( "print_jsdom_message", () => {
grunt.log.writeln( "Node.js 17 or newer detected, skipping jsdom tests..." );
} );
Expand All @@ -393,7 +427,7 @@ module.exports = function( grunt ) {
runIfNewNode( "newer:eslint:dist" )
] );

grunt.registerTask( "test:fast", runIfNewNode( "node_smoke_tests" ) );
grunt.registerTask( "test:fast", [ "node_smoke_tests:commonjs:jquery" ] );
grunt.registerTask( "test:slow", [
runIfNewNode( "promises_aplus_tests" ),

Expand All @@ -419,18 +453,14 @@ module.exports = function( grunt ) {
"build:*:*",
runIfNewNode( "newer:eslint:dev" ),
"newer:minify",
"remove_map_comment",
"dist:*",
"qunit_fixture",
"compare_size"
] );

grunt.registerTask( "default", [
runIfNewNode( "eslint:dev" ),
"build:*:*",
"minify",
"remove_map_comment",
"dist:*",
"build-all-variants",
"test:prepare",
runIfNewNode( "eslint:dist" ),
"test:fast",
Expand Down
26 changes: 25 additions & 1 deletion README.md
Expand Up @@ -111,7 +111,7 @@ The build process shows a message for each dependent module it excludes or inclu

##### AMD name

As an option, you can set the module name for jQuery's AMD definition. By default, it is set to "jquery", which plays nicely with plugins and third-party libraries, but there may be cases where you'd like to change this. Simply set the `"amd"` option:
As an option, you can set the module name for jQuery's AMD definition. By default, it is set to "jquery", which plays nicely with plugins and third-party libraries, but there may be cases where you'd like to change this. Simply pass it to the `--amd` parameter:

```bash
grunt custom --amd="custom-name"
Expand All @@ -123,6 +123,30 @@ Or, to define anonymously, set the name to an empty string.
grunt custom --amd=""
```

##### File name

The default name for the built jQuery file is `jquery.js`; it is placed under the `dist/` directory. It's possible to change the file name using the `--filename` parameter:

```bash
grunt custom:slim --filename="jquery.slim.js"
```

This would create a slim version of jQuery and place it under `dist/jquery.slim.js`. In fact, this is exactly the command we use to generate the slim jQuery during the release process.

##### ECMAScript Module (ESM) mode

By default, jQuery generates a regular script JavaScript file. You can also generate an ECMAScript module exporting `jQuery` as the default export using the `--esm` parameter:

```bash
grunt custom --esm
```

The default is `script` but you can also pass it explicitly via `--no-esm`:

```bash
grunt custom --no-esm
```

#### Custom Build Examples

To create a custom build, first check out the version:
Expand Down

0 comments on commit 8be4c0e

Please sign in to comment.