-
Notifications
You must be signed in to change notification settings - Fork 780
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Demos: Add Rollup and Webpack example mixing ESM import and CJS requi…
…re() Co-authored-by: Michał Gołębiowski-Owczarek <[email protected]>
- Loading branch information
Showing
20 changed files
with
483 additions
and
22 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
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,145 @@ | ||
const cp = require('child_process'); | ||
const path = require('path'); | ||
const DIR = path.join(__dirname, 'bundlers'); | ||
|
||
function normalize (str) { | ||
return str | ||
.replace(/^localhost:\d+/g, 'localhost:8000') | ||
.replace(/\b\d+ms\b/g, '42ms'); | ||
} | ||
|
||
QUnit.module('bundlers', { | ||
before: async (assert) => { | ||
assert.timeout(60_000); | ||
|
||
cp.execSync('npm install --no-audit --update-notifier=false', { cwd: DIR, encoding: 'utf8' }); | ||
|
||
await import('./bundlers/build.mjs'); | ||
} | ||
}); | ||
|
||
QUnit.test.each('test in Node.js [direct]', [ | ||
'./tmp/import-default.cjs.js', | ||
'./tmp/import-named.cjs.js', | ||
'./tmp/require-default.cjs.js' | ||
], function (assert, fileName) { | ||
const actual = cp.execFileSync(process.execPath, | ||
[ | ||
'--input-type=module', | ||
'-e', | ||
`import ${JSON.stringify(fileName)}; QUnit.start();` | ||
], | ||
{ cwd: DIR, env: { qunit_config_reporters_tap: 'true' }, encoding: 'utf8' } | ||
); | ||
const expected = ` | ||
1..1 | ||
# pass 1 | ||
# skip 0 | ||
# todo 0 | ||
# fail 0`.trim(); | ||
|
||
assert.pushResult({ result: actual.includes(expected), actual, expected }, 'stdout'); | ||
}); | ||
|
||
QUnit.test.each('test in Node.js [indirect]', [ | ||
'./tmp/import-indirect.cjs.js', | ||
'./tmp/require-indirect.cjs.js' | ||
], function (assert, fileName) { | ||
const actual = cp.execFileSync(process.execPath, | ||
[ | ||
'--input-type=module', | ||
'-e', | ||
`import ${JSON.stringify(fileName)}; QUnit.start();` | ||
], | ||
{ cwd: DIR, env: { qunit_config_reporters_tap: 'true' }, encoding: 'utf8' } | ||
); | ||
const expected = ` | ||
1..4 | ||
# pass 4 | ||
# skip 0 | ||
# todo 0 | ||
# fail 0`.trim(); | ||
|
||
assert.pushResult({ result: actual.includes(expected), actual, expected }, 'stdout'); | ||
}); | ||
|
||
QUnit.test('test in browser', function (assert) { | ||
const expected = `Running "connect:all" (connect) task | ||
Started connect web server on http://localhost:8000 | ||
Running "qunit:all" (qunit) task | ||
Testing http://localhost:8000/tmp/test-import-default.es.html .OK | ||
>> passed test "import-default" | ||
Testing http://localhost:8000/tmp/test-import-default.iife.html .OK | ||
>> passed test "import-default" | ||
Testing http://localhost:8000/tmp/test-import-default.umd.html .OK | ||
>> passed test "import-default" | ||
Testing http://localhost:8000/tmp/test-import-default.webpack.html .OK | ||
>> passed test "import-default" | ||
Testing http://localhost:8000/tmp/test-import-indirect.es.html ....OK | ||
>> passed test "import-default" | ||
>> passed test "import-named" | ||
>> passed test "require-default" | ||
>> passed test "import-indirect" | ||
Testing http://localhost:8000/tmp/test-import-indirect.iife.html ....OK | ||
>> passed test "import-default" | ||
>> passed test "import-named" | ||
>> passed test "require-default" | ||
>> passed test "import-indirect" | ||
Testing http://localhost:8000/tmp/test-import-indirect.umd.html ....OK | ||
>> passed test "import-default" | ||
>> passed test "import-named" | ||
>> passed test "require-default" | ||
>> passed test "import-indirect" | ||
Testing http://localhost:8000/tmp/test-import-indirect.webpack.html ....OK | ||
>> passed test "import-default" | ||
>> passed test "import-named" | ||
>> passed test "require-default" | ||
>> passed test "import-indirect" | ||
Testing http://localhost:8000/tmp/test-import-named.es.html .OK | ||
>> passed test "import-named" | ||
Testing http://localhost:8000/tmp/test-import-named.iife.html .OK | ||
>> passed test "import-named" | ||
Testing http://localhost:8000/tmp/test-import-named.umd.html .OK | ||
>> passed test "import-named" | ||
Testing http://localhost:8000/tmp/test-import-named.webpack.html .OK | ||
>> passed test "import-named" | ||
Testing http://localhost:8000/tmp/test-require-default.es.html .OK | ||
>> passed test "require-default" | ||
Testing http://localhost:8000/tmp/test-require-default.iife.html .OK | ||
>> passed test "require-default" | ||
Testing http://localhost:8000/tmp/test-require-default.umd.html .OK | ||
>> passed test "require-default" | ||
Testing http://localhost:8000/tmp/test-require-default.webpack.html .OK | ||
>> passed test "require-default" | ||
Testing http://localhost:8000/tmp/test-require-indirect.es.html ....OK | ||
>> passed test "import-default" | ||
>> passed test "import-named" | ||
>> passed test "require-default" | ||
>> passed test "require-indirect" | ||
Testing http://localhost:8000/tmp/test-require-indirect.iife.html ....OK | ||
>> passed test "import-default" | ||
>> passed test "import-named" | ||
>> passed test "require-default" | ||
>> passed test "require-indirect" | ||
Testing http://localhost:8000/tmp/test-require-indirect.umd.html ....OK | ||
>> passed test "import-default" | ||
>> passed test "import-named" | ||
>> passed test "require-default" | ||
>> passed test "require-indirect" | ||
Testing http://localhost:8000/tmp/test-require-indirect.webpack.html ....OK | ||
>> passed test "import-default" | ||
>> passed test "import-named" | ||
>> passed test "require-default" | ||
>> passed test "require-indirect" | ||
>> 44 tests completed in 42ms, with 0 failed, 0 skipped, and 0 todo. | ||
Done.`; | ||
|
||
const actual = cp.execSync('node_modules/.bin/grunt test', { | ||
cwd: DIR, | ||
env: { PATH: process.env.PATH }, | ||
encoding: 'utf8' | ||
}); | ||
assert.equal(normalize(actual).trim(), expected); | ||
}); |
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,39 @@ | ||
/* eslint-env node */ | ||
module.exports = function (grunt) { | ||
grunt.loadNpmTasks('grunt-contrib-connect'); | ||
grunt.loadNpmTasks('grunt-contrib-qunit'); | ||
|
||
grunt.initConfig({ | ||
connect: { | ||
all: { | ||
options: { | ||
useAvailablePort: true, | ||
base: '.' | ||
} | ||
} | ||
}, | ||
qunit: { | ||
options: { | ||
}, | ||
all: ['tmp/test-*.html'] | ||
} | ||
}); | ||
|
||
grunt.event.once('connect.all.listening', function (_host, port) { | ||
grunt.config('qunit.options.httpBase', `http://localhost:${port}`); | ||
// console.log(grunt.config()); // DEBUG | ||
}); | ||
|
||
let results = []; | ||
grunt.event.on('qunit.on.testEnd', function (test) { | ||
results.push( | ||
`>> ${test.status} test "${test.fullName.join(' > ')}"` | ||
); | ||
}); | ||
grunt.event.on('qunit.on.runEnd', function () { | ||
grunt.log.writeln(results.join('\n')); | ||
results = []; | ||
}); | ||
|
||
grunt.registerTask('test', ['connect', 'qunit']); | ||
}; |
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,17 @@ | ||
# QUnit ♥️ Rollup & Webpack | ||
|
||
See also <https://rollupjs.org/> and <https://webpack.js.org/>. | ||
|
||
```bash | ||
npm run build | ||
npm test | ||
``` | ||
|
||
``` | ||
Running "qunit:all" (qunit) task | ||
Testing http://localhost:8000/test.html .OK | ||
>> passed test "example" | ||
>> 1 test completed in 0ms, with 0 failed, 0 skipped, and 0 todo. | ||
Done. | ||
``` |
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,139 @@ | ||
import fs from 'node:fs'; | ||
import path from 'node:path'; | ||
import url from 'node:url'; | ||
|
||
import { rollup } from 'rollup'; | ||
import resolve from '@rollup/plugin-node-resolve'; | ||
import commonjs from '@rollup/plugin-commonjs'; | ||
import webpack from 'webpack'; | ||
|
||
const dirname = path.dirname(url.fileURLToPath(import.meta.url)); | ||
const tmpDir = path.join(dirname, 'tmp'); | ||
|
||
const inputs = [ | ||
`${dirname}/test/import-default.js`, | ||
`${dirname}/test/import-named.js`, | ||
`${dirname}/test/import-indirect.js`, | ||
`${dirname}/test/require-default.cjs`, | ||
`${dirname}/test/require-indirect.cjs` | ||
]; | ||
|
||
const htmlTemplate = `<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<title>{{title}}</title> | ||
<link rel="stylesheet" href="../node_modules/qunit/qunit/qunit.css"> | ||
{{scriptTag}} | ||
</head> | ||
<body> | ||
<div id="qunit"></div> | ||
</body> | ||
</html> | ||
`; | ||
|
||
// Rollup configuration | ||
const rollupOutputs = [ | ||
{ | ||
dir: tmpDir, | ||
entryFileNames: '[name].[format].js', | ||
format: 'es' | ||
}, | ||
{ | ||
dir: tmpDir, | ||
entryFileNames: '[name].[format].js', | ||
format: 'cjs' | ||
}, | ||
{ | ||
dir: tmpDir, | ||
entryFileNames: '[name].[format].js', | ||
format: 'iife' | ||
}, | ||
{ | ||
dir: tmpDir, | ||
entryFileNames: '[name].[format].js', | ||
format: 'umd', | ||
name: 'UNUSED' | ||
} | ||
]; | ||
async function * buildRollup () { | ||
const plugins = [commonjs(), resolve()]; | ||
|
||
for (const input of inputs) { | ||
const bundle = await rollup({ | ||
input, | ||
plugins, | ||
// Ignore "output.name" warning for require-default.iife.js | ||
onwarn: () => {} | ||
}); | ||
|
||
for (const outputOptions of rollupOutputs) { | ||
const { output } = await bundle.write(outputOptions); | ||
const fileName = output[0].fileName; | ||
yield fileName; | ||
} | ||
} | ||
} | ||
|
||
// https://webpack.js.org/api/node/#webpack | ||
async function * buildWebpack () { | ||
for (const input of inputs) { | ||
const config = { | ||
entry: input, | ||
output: { | ||
filename: path.basename(input).replace(/\.(cjs|js)$/, '.webpack.js'), | ||
path: tmpDir | ||
} | ||
}; | ||
await new Promise((resolve, reject) => { | ||
webpack(config, (err, stats) => { | ||
if (err || stats.hasErrors()) { | ||
reject(err); | ||
return; | ||
} | ||
resolve(); | ||
}); | ||
}); | ||
yield config.output.filename; | ||
} | ||
} | ||
|
||
await (async function main () { | ||
// Clean up | ||
fs.rmSync(tmpDir, { force: true, recursive: true }); | ||
|
||
const gRollup = buildRollup(); | ||
const gWebpack = buildWebpack(); | ||
|
||
for await (const fileName of gRollup) { | ||
console.log('... built ' + fileName); | ||
|
||
if (!fileName.endsWith('.cjs.js')) { | ||
const html = htmlTemplate | ||
.replace('{{title}}', fileName) | ||
.replace('{{scriptTag}}', ( | ||
fileName.endsWith('.es.js') | ||
? `<script src="./${fileName}" type="module"></script>` | ||
: `<script src="./${fileName}"></script>` | ||
)); | ||
|
||
fs.writeFileSync( | ||
`${tmpDir}/test-${fileName.replace('.js', '')}.html`, | ||
html | ||
); | ||
} | ||
} | ||
for await (const fileName of gWebpack) { | ||
console.log('... built ' + fileName); | ||
|
||
const html = htmlTemplate | ||
.replace('{{title}}', fileName) | ||
.replace('{{scriptTag}}', ( | ||
`<script src="./${fileName}"></script>` | ||
)); | ||
|
||
fs.writeFileSync( | ||
`${tmpDir}/test-${fileName.replace('.js', '')}.html`, | ||
html | ||
); | ||
} | ||
}()); |
Empty file.
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,17 @@ | ||
{ | ||
"private": true, | ||
"devDependencies": { | ||
"@rollup/plugin-commonjs": "^26.0.1", | ||
"@rollup/plugin-node-resolve": "^15.2.3", | ||
"grunt": "1.6.1", | ||
"grunt-contrib-connect": "^5.0.0", | ||
"grunt-contrib-qunit": "10.1.1", | ||
"qunit": "file:../..", | ||
"rollup": "^4.18.0", | ||
"webpack": "^5.92.0" | ||
}, | ||
"scripts": { | ||
"build": "node build.mjs", | ||
"test": "grunt test" | ||
} | ||
} |
Oops, something went wrong.