Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: CI
on: pull_request

jobs:
test:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v1
- uses: actions/setup-node@v1
with:
node-version: "14.x"
- name: Setup Testing Infra
run: |
cd test
npm install

- name: "CommonJS Test"
run: |
cd test/cjs
npm run test

- name: "ES Modules Test"
run: |
cd test/esm-node-native
npm run test

- name: "Rollup Tree-shaking Test"
run: |
cd test/rollup-modules
npm run test

- name: "Webpack Tree-shaking Test"
run: |
cd test/webpack-modules
npm run test
1 change: 1 addition & 0 deletions .npmignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
.github
bower.json
docs
test
51 changes: 51 additions & 0 deletions modules/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { createRequire } from "module";
const {
__extends,
__assign,
__rest,
__decorate,
__param,
__metadata,
__awaiter,
__generator,
__exportStar,
__createBinding,
__values,
__read,
__spread,
__spreadArrays,
__await,
__asyncGenerator,
__asyncDelegator,
__asyncValues,
__makeTemplateObject,
__importStar,
__importDefault,
__classPrivateFieldGet,
__classPrivateFieldSet,
} = createRequire(import.meta.url)("../tslib.js");
export {
__extends,
__assign,
__rest,
__decorate,
__param,
__metadata,
__awaiter,
__generator,
__exportStar,
__createBinding,
__values,
__read,
__spread,
__spreadArrays,
__await,
__asyncGenerator,
__asyncDelegator,
__asyncValues,
__makeTemplateObject,
__importStar,
__importDefault,
__classPrivateFieldGet,
__classPrivateFieldSet,
};
3 changes: 3 additions & 0 deletions modules/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"type": "module"
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This pattern definitely works if the .js extension is important for both. I take it that is the constraint you're working too, even if .mjs would be slightly simpler.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Curious, what was the point of adding this almost empty package.json with no package name, no package version?

Sincerely,
ES Module Bundlers

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://nodejs.org/api/packages.html#type

The "type" field defines the module format that Node.js uses for all .js files that have that package.json file as their nearest parent.

Copy link

@Sweetog Sweetog Jun 26, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, is it best to comprehensively interpret this spec like this though? To just drop a nested, nearly empty package.json in a distribution directory, when thinking about all the nuances that go into an NPM package and bundling/transpiling packages?

And how is an NPM package like pkg-dir expected to behave now, in it's claim to:

Find the root directory of a Node.js project or npm package

The above pkg-dir behavior will fail to resolve the root of the NPM package for tslib after an ESM bundler follows to path ./imports/index.js declared in package.json#exports['.'].imports and then executes pkg-dir with a cwd of: node_modules/tslib/imports/index.js

It seems the case that NOT using the .mjs extension was a shortcut and may be more the problem here

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, is it best to comprehensively interpret this spec like this though?

The spec is quite intentionally written like this as far as I know. It intentionally doesn't use something like "package.json at the root of the package directory" multiple times

To just drop a nested, nearly empty package.json in a distribution directory, when thinking about all the nuances that go into an NPM package and bundling/transpiling packages?

Even before node has supported .mjs, .cjs, package.json#type and more, it was already possible to define nested package.json files. It was possible to put package.json#main there to "redirect" the request to another location. I've been using this for years already.

And how is an NPM package like pkg-dir expected to behave now, in it's claim to:

I'm not sure if this package is implemented correctly but a lot of similar resolvers were implemented correctly in the past. All modern module bundlers etc already work just OK with those nested package.json files. The rule, in fact, is quite simple if you want to just grab the root of a pkg, arguably you wouldn't even have to look for package.json files but rather just find a directory nested directly within node_modules directory

9 changes: 8 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,12 @@
"module": "tslib.es6.js",
"jsnext:main": "tslib.es6.js",
"typings": "tslib.d.ts",
"sideEffects": false
"sideEffects": false,
"exports": {
".": {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please provide "module" condition as well. It's going to be supported by the upcoming webpack 5 and will allow it to keep only a single copy of tslib in the bundle. Point of reference: https://gist.github.com/sokra/e032a0f17c1721c71cfced6f14516c62#reference-syntax

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm open to covering this in a new PR, that gist isn't really enough docs for me to go with yet

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, can be added afterwards.

There are no real docs for this yet on their page but this gist has been updated multiple times when they have been iterating over semantics. This is already implemented and shipped in webpack 5 RC.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Andarist do you have any examples of packages using the "module" condition successfully for reference here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@guybedford I did not (mainly because conditional exports themselves are rather rare to find so far), but I've decided to showcase this using one of my smaller modules. Here are exports that I have defined:
https://github.com/Andarist/callbag-last-element/blob/07099fd55b4dfff80a7697065c71ce9b5fc07ade/package.json#L7-L14
and here is the webpack output:
https://github.com/Andarist/webpack-module-condition-test/tree/7bca3a5ae4f07b5429c7b36db3d43b2072b39cf2/src
Notice how last function is only there a single time in this bundle even when mixing ESM and CJS files.

The input for this is as simple as:

// cjs-file.js
module.exports = require("callbag-last-element").default;

// index.js
import lastElement from "callbag-last-element";
import lastElementFromCjs from "./cjs-file";

console.log({ lastElement, lastElementFromCjs });

and can be found here (same repo)

"import": "./modules/index.js",
"default": "./tslib.js"
},
"./": "./"
}
}
3 changes: 3 additions & 0 deletions test/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package-lock.json
rollup-modules/output
webpack-modules/dist
4 changes: 4 additions & 0 deletions test/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
### Tests

Each folder has a `test` script which imports `tslib` via node_modules.
In order to run these tests, you first need to run `npm install` in this folder.
7 changes: 7 additions & 0 deletions test/cjs/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const { __awaiter } = require("tslib");

const testFunction = (textToPrint) => __awaiter(void 0, void 0, void 0, function* () {
console.log(`State: ${textToPrint}`);
});

testFunction("Works")
5 changes: 5 additions & 0 deletions test/cjs/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"scripts": {
"test": "node index.js"
}
}
7 changes: 7 additions & 0 deletions test/esm-node-native/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { __awaiter } from "tslib";

export const testFunction = (textToPrint) => __awaiter(void 0, void 0, void 0, function* () {
console.log(`State: ${textToPrint}`);
});

testFunction("Works")
6 changes: 6 additions & 0 deletions test/esm-node-native/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"type": "module",
"scripts": {
"test": "node --experimental-specifier-resolution=node index.js"
}
}
9 changes: 9 additions & 0 deletions test/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"dependencies": {
"tslib": "file:..",
"rollup": "2.28.2",
"@rollup/plugin-node-resolve": "9.0.0",
"webpack": "4.44.2",
"webpack-cli": "3.3.12"
}
}
7 changes: 7 additions & 0 deletions test/rollup-modules/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { __awaiter } from "tslib";

export const testFunction = (textToPrint) => __awaiter(void 0, void 0, void 0, function* () {
console.log(`State: ${textToPrint}`);
});

testFunction("Works")
5 changes: 5 additions & 0 deletions test/rollup-modules/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"scripts": {
"test": "../node_modules/.bin/rollup -c rollup.config.js && node output/index.js"
}
}
10 changes: 10 additions & 0 deletions test/rollup-modules/rollup.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { nodeResolve } from '@rollup/plugin-node-resolve';

export default {
input: 'index.js',
output: {
dir: 'output',
format: 'cjs'
},
plugins: [nodeResolve()]
};
7 changes: 7 additions & 0 deletions test/webpack-modules/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { __awaiter } from "tslib";

export const testFunction = (textToPrint) => __awaiter(void 0, void 0, void 0, function* () {
console.log(`State: ${textToPrint}`);
});

testFunction("Works")
5 changes: 5 additions & 0 deletions test/webpack-modules/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"scripts": {
"test": "../node_modules/.bin/webpack && node dist/main.js"
}
}
4 changes: 4 additions & 0 deletions test/webpack-modules/webpack.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module.exports = {
mode: "production",
entry: "./index"
}