Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for generating native module imports and systemjs fallback imports (implementation included, if useful for anyone) #27

Open
JohnnyFun opened this issue Oct 22, 2019 · 0 comments

Comments

@JohnnyFun
Copy link

JohnnyFun commented Oct 22, 2019

I like the approach of the "rollup-starter-code-splitting" where they rollup 2 folders: one that is in "es" format and another in "system" format (systemjs).

I modified your source to implement this, and figured I'd post it here, in case you'd be interested in adding it to the project if it makes sense to add.

The final output looks something like this:

<!DOCTYPE html>
<html>
...
<body>
	<script>
		import("/scripts/module/app-entry-bc2e6da4.js")
		window.supportsDynamicImport = true
	</script>
	<script>
		if (!window.supportsDynamicImport) {

			var dep0 = document.createElement('script');
			dep0.src = 'https://cdn.jsdelivr.net/npm/promise-polyfill@8/dist/polyfill.min.js';
			document.head.appendChild(dep0);
			dep0.addEventListener('load', function () { importIfAllDepsLoaded() })


			var dep1 = document.createElement('script');
			dep1.src = '/scripts/nomodule/systemjs/s.min.js';
			document.head.appendChild(dep1);
			dep1.addEventListener('load', function () { importIfAllDepsLoaded() })


			var depsLoaded = 0
			function importIfAllDepsLoaded() {
				depsLoaded++;
				if (depsLoaded < 2) return;
				System.import('/scripts/nomodule/app-entry-07432d5a.js');
			}

		}
	</script>
</body>

</html>

I added moduleImports option to the rollup-plugin that can be configured like:

html({
      template: 'src/template.html',
      inject: 'head',
      filename: 'index.html',
      dest: 'public',
      absolute: true,
      ignore: /(?:chunk-)|(?:systemjs\/)/i,
      moduleImports: [
        {
          test: /\/module\/app-entry/i,
          format: 'es'
        },
        {
          test: /\/nomodule\/app-entry/i,
          format: 'system',
          dependencies: [
            '/scripts/promise-polyfill.js', // systemjs requires Promise, ie11 does not have it
            '/scripts/systemjs/s.min.js' // systemjs runtime
          ]
        }
      ]
    }),

and implemented it like so:

...
if (type === 'js') {
	const moduleImport = moduleImports.find(i => i.test.test(file))
	if (moduleImport) {
		addModuleImport(src, body, moduleImport);
	} else ...
}
...

function addModuleImport(src, body, moduleImport) {
	if (moduleImport.format === 'es') {
		addEsImport(moduleImport, src, body);
	} else if (moduleImport.format === 'system') {
		addSystemjsImport(moduleImport, src, body);
	} else {
		throw new Error(`unsupported module import format "${moduleImport.format}"`);
	}
}

function addEsImport(moduleImport, src, body) {
	if (moduleImport.dependencies != null && moduleImport.dependencies.length > 0) {
		throw new Error('You shouldn\'t need any dependencies loaded for native modules. "dependencies" are for loading in browser module-loader runtimes and their needed polyfills.');
	}
	// TODO: add a <script module...in head...
	body.append(`
		<script>
			import("${src}")
			window.supportsDynamicImport = true
		</script>`);
}

function addSystemjsImport(moduleImport, src, body) {
	const deps = moduleImport.dependencies.map((d, i) => {
		const name = `dep${i}`;
		return {
			name,
			script: `
				var ${name} = document.createElement('script');
				${name}.src = '${d}';
				document.head.appendChild(${name});
				${name}.addEventListener('load', function () { importIfAllDepsLoaded() })
			`
		};
	});
	const importIfAllDepsLoaded = `
		var depsLoaded = 0
		function importIfAllDepsLoaded() {
			depsLoaded++;
			if (depsLoaded < ${deps.length}) return;
			System.import('${src}');
		}
	`

	body.append(`
		<script>
			if (!window.supportsDynamicImport) {
				${deps.map(d => d.script).join('\n')}
				${importIfAllDepsLoaded}
			}
		</script>`);
}
@JohnnyFun JohnnyFun changed the title Support for generating native module imports and systemjs fallback imports Support for generating native module imports and systemjs fallback imports (implementation included, if useful for anyone) Oct 22, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant