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

Thanks for a great plugin! I'd suggest adding dynamic import syntax to the readme! :) #224

Open
LouisStAmour opened this issue May 26, 2019 · 2 comments

Comments

@LouisStAmour
Copy link

Not sure if this is working as intended or just a happy byproduct of Babel improvements, but I was able to use rewire APIs not just with top-level ES6 imports but also with dynamic imports using ES6 import() syntax. And with webpack, I can remove cached modules to force their re-evaluation. An example (assuming '../src/someFunc.js' contains a top-level const Q that it doesn't export, which in turn has a set named queue):

it('supports dynamic imports -- sweet', async () => {
	const exportedFunc = await import('../src/someFunc.js');
	const Q = exportedFunc.__get__('Q');
	expect(Q.queue.size).to.equal(0);
	Q.queue.add('test');
	expect(Q.queue.size).to.equal(1);
	// NOTE: The following line is required or webpack will return the same module instance in the next import...
	delete require.cache[require.resolve('../src/someFunc.js')];
	const exportedFunc = await import('../src/someFunc.js');
	const Q = exportedFunc.__get__('Q');
	expect(Q.queue.size).to.equal(0);
});

Very happy with how this is working out! :)

If it helps anybody, I'm using open-wc's Karma config with webpack config modified as follows (I've included the original open-wc Karma webpack config inline...):

{
	webpack: {
		watch: true,
		mode: 'development',
		devtool: 'inline-cheap-module-source-map',

		resolve: {
			mainFields: [
				// current leading de-facto standard - see https://github.com/rollup/rollup/wiki/pkg.module
				'module',
				// previous de-facto standard, superceded by `module`, but still in use by some packages
				'jsnext:main',
				// standard package.json fields
				'browser',
				'main',
			],
		},

		module: {
			rules: [
				coverage && {
					test: /\.js$/,
					loader: require.resolve('istanbul-instrumenter-loader'),
					enforce: 'post',
					include: path.resolve('./'),
					exclude: /node_modules|bower_components|\.(spec|test)\.js$/,
					options: {
						esModules: true,
					},
				},

				legacy && {
					test: /\.js$|\.ts$/,
					use: {
						loader: 'babel-loader',

						options: {
							plugins: [
								require.resolve('@babel/plugin-syntax-dynamic-import'),
								require.resolve('@babel/plugin-syntax-import-meta'),
								// webpack does not support import.meta.url yet, so we rewrite them in babel
								[require.resolve('babel-plugin-bundled-import-meta'), { importStyle: 'baseURI' }],
							].filter(_ => !!_),

							presets: [[require.resolve('@babel/preset-env'), { targets: 'IE 11' }]],
						},
					},
				},

				!legacy && {
					test: /\.js$/,
					loader: require.resolve('@open-wc/webpack-import-meta-loader'),
				},
				{
					test: /\.js$|\.ts$/,
					exclude: /node_modules|bower_components|\.(spec|test)\.js$/,
					use: {
						loader: 'babel-loader',
						options: {
							plugins: [require.resolve('babel-plugin-rewire')].filter(_ => !!_),
							sourceMaps: 'both',
						},
					},
				},
			].filter(_ => !!_),
	},
}
@LouisStAmour LouisStAmour changed the title Thanks for a great module! I'd suggest adding dynamic import syntax to the readme! :) Thanks for a great plugin! I'd suggest adding dynamic import syntax to the readme! :) May 26, 2019
@LouisStAmour
Copy link
Author

To help mask the above webpack delete nastiness, I made a very simple wrapper using promises:

const importAndForget = filename => {
	return import(filename).finally(() => {
		delete require.cache[require.resolve(filename)];
	});
};

which simplifies the above example to:

it('supports dynamic imports -- sweet', async () => {
	importAndForget('../src/someFunc.js').then(module => {
		const Q = module.__get__('Q');
		expect(Q.queue.size).to.equal(0);
		Q.queue.add('test');
		expect(Q.queue.size).to.equal(1);
	});
	importAndForget('../src/someFunc.js').then(module => {
		const Q = module.__get__('Q');
		expect(Q.queue.size).to.equal(0);
	});
});

@LouisStAmour
Copy link
Author

LouisStAmour commented May 26, 2019

Had a hard time making the filenames dynamic while still keeping things await-compatible, so I ended up with the following function hard-coded:

function loadSomeFunc() {
	delete require.cache[require.resolve('../src/someFunc.js')];
	return import('../src/someFunc.js');
}

which can be used as follows:

	it('supports dynamic imports -- sweet', async () => {
		let module = await loadSomeFunc();
		let Q = module.__get__('Q');
		expect(Q.queue.size).to.equal(0);
		Q.queue.add('test');
		expect(Q.queue.size).to.equal(1);
		module = await loadSomeFunc();
		Q = module.__get__('Q');
		expect(Q.queue.size).to.equal(0);
	});

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