From ef3f8ae90c22d304c510b6ac34988b715b2202f2 Mon Sep 17 00:00:00 2001 From: Non <19non91@gmail.com> Date: Wed, 13 Jan 2021 20:50:32 +0200 Subject: [PATCH] Support Webpack 5, drop copypasted webpack-virtual-modules Fixes #139, Fixes #131, Fixes #126 Co-authored-by: Smittyvb --- README.md | 7 ++++ index.js | 33 +++++++--------- lib/virtual-stats.js | 89 -------------------------------------------- lib/virtual.js | 89 -------------------------------------------- test/loader.spec.js | 2 +- 5 files changed, 22 insertions(+), 198 deletions(-) delete mode 100644 lib/virtual-stats.js delete mode 100644 lib/virtual.js diff --git a/README.md b/README.md index 61d5a0a1..44a80a31 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,13 @@ Configure inside your `webpack.config.js`: test: /\.(html|svelte)$/, exclude: /node_modules/, use: 'svelte-loader' + }, + { + // required to prevent errors from Svelte on Webpack 5+, omit on Webpack 4 + test: /node_modules\/svelte\/.*\.mjs$/, + resolve: { + fullySpecified: false + } } ... ] diff --git a/index.js b/index.js index 0e3f5f4d..6b0afd5b 100644 --- a/index.js +++ b/index.js @@ -1,6 +1,5 @@ const { basename, extname, relative } = require('path'); const { getOptions } = require('loader-utils'); -const VirtualModules = require('./lib/virtual'); const hotApi = require.resolve('./lib/hot-api.js'); @@ -96,20 +95,22 @@ function deprecatePreprocessOptions(options) { options.preprocess = options.preprocess || preprocessOptions; } -const virtualModuleInstances = new Map(); +const virtualModules = new Map(); +let index = 0; module.exports = function(source, map) { - if (this._compiler && !virtualModuleInstances.has(this._compiler)) { - virtualModuleInstances.set(this._compiler, new VirtualModules(this._compiler)); - } - - const virtualModules = virtualModuleInstances.get(this._compiler); - this.cacheable(); - + const options = Object.assign({}, getOptions(this)); const callback = this.async(); + if (options.cssPath) { + const css = virtualModules.get(options.cssPath); + virtualModules.delete(options.cssPath); + callback(null, css); + return; + } + const isServer = this.target === 'node' || (options.generate && options.generate == 'ssr'); const isProduction = this.minimize || process.env.NODE_ENV === 'production'; @@ -161,17 +162,11 @@ module.exports = function(source, map) { } if (options.emitCss && css.code) { - const cssFilepath = compileOptions.filename.replace( - /\.[^/.]+$/, - `.svelte.css` - ); - + const resource = posixify(compileOptions.filename); + const cssPath = `${resource}.${index++}.css`; css.code += '\n/*# sourceMappingURL=' + css.map.toUrl() + '*/'; - js.code = js.code + `\nimport '${posixify(cssFilepath)}';\n`; - - if (virtualModules) { - virtualModules.writeModule(cssFilepath, css.code); - } + js.code += `\nimport '${cssPath}!=!svelte-loader?cssPath=${cssPath}!${resource}'\n;`; + virtualModules.set(cssPath, css.code); } callback(null, js.code, js.map); diff --git a/lib/virtual-stats.js b/lib/virtual-stats.js deleted file mode 100644 index 4e1b1dee..00000000 --- a/lib/virtual-stats.js +++ /dev/null @@ -1,89 +0,0 @@ -/** - * Used to cache a stats object for the virtual file. - * Extracted from the `mock-fs` package. - * - * @author Tim Schaub http://tschaub.net/ - * @link https://github.com/tschaub/mock-fs/blob/master/lib/binding.js - * @link https://github.com/tschaub/mock-fs/blob/master/license.md - */ - -/* eslint-disable no-restricted-syntax, no-prototype-builtins, no-continue */ -/* eslint-disable no-bitwise, no-underscore-dangle */ - -'use strict'; - -var constants = require('constants'); - -/** - * Create a new stats object. - * @param {Object} config Stats properties. - * @constructor - */ -function VirtualStats(config) { - for (var key in config) { - if (!config.hasOwnProperty(key)) { - continue; - } - this[key] = config[key]; - } -} - -/** - * Check if mode indicates property. - * @param {number} property Property to check. - * @return {boolean} Property matches mode. - */ -VirtualStats.prototype._checkModeProperty = function(property) { - return (this.mode & constants.S_IFMT) === property; -}; - -/** - * @return {Boolean} Is a directory. - */ -VirtualStats.prototype.isDirectory = function() { - return this._checkModeProperty(constants.S_IFDIR); -}; - -/** - * @return {Boolean} Is a regular file. - */ -VirtualStats.prototype.isFile = function() { - return this._checkModeProperty(constants.S_IFREG); -}; - -/** - * @return {Boolean} Is a block device. - */ -VirtualStats.prototype.isBlockDevice = function() { - return this._checkModeProperty(constants.S_IFBLK); -}; - -/** - * @return {Boolean} Is a character device. - */ -VirtualStats.prototype.isCharacterDevice = function() { - return this._checkModeProperty(constants.S_IFCHR); -}; - -/** - * @return {Boolean} Is a symbolic link. - */ -VirtualStats.prototype.isSymbolicLink = function() { - return this._checkModeProperty(constants.S_IFLNK); -}; - -/** - * @return {Boolean} Is a named pipe. - */ -VirtualStats.prototype.isFIFO = function() { - return this._checkModeProperty(constants.S_IFIFO); -}; - -/** - * @return {Boolean} Is a socket. - */ -VirtualStats.prototype.isSocket = function() { - return this._checkModeProperty(constants.S_IFSOCK); -}; - -module.exports = VirtualStats; diff --git a/lib/virtual.js b/lib/virtual.js deleted file mode 100644 index 307e2c27..00000000 --- a/lib/virtual.js +++ /dev/null @@ -1,89 +0,0 @@ -var VirtualStats = require('./virtual-stats'); - -var inode = 45000000; - -// Adapted from https://github.com/sysgears/webpack-virtual-modules -// MIT Licensed https://github.com/sysgears/webpack-virtual-modules/blob/master/LICENSE - -/** - * @param {Compiler} compiler - the webpack compiler - */ -function VirtualModulesPlugin(compiler) { - this.compiler = compiler; - - if (!compiler.inputFileSystem._writeVirtualFile) { - var originalPurge = compiler.inputFileSystem.purge; - - compiler.inputFileSystem.purge = function() { - if (originalPurge) { - originalPurge.call(this, arguments); - } - if (this._virtualFiles) { - Object.keys(this._virtualFiles).forEach( - function(file) { - var data = this._virtualFiles[file]; - setData(this._statStorage, file, [null, data.stats]); - setData(this._readFileStorage, file, [null, data.contents]); - }.bind(this) - ); - } - }; - - compiler.inputFileSystem._writeVirtualFile = function(file, stats, contents) { - this._virtualFiles = this._virtualFiles || {}; - this._virtualFiles[file] = { stats: stats, contents: contents }; - setData(this._statStorage, file, [null, stats]); - setData(this._readFileStorage, file, [null, contents]); - }; - } - - const watchRunHook = (watcher, callback) => { - this._watcher = watcher.compiler || watcher; - callback(); - }; - - if (compiler.hooks) { - compiler.hooks.watchRun.tapAsync('VirtualModulesPlugin', watchRunHook); - } else { - compiler.plugin('watch-run', watchRunHook); - } -} - -VirtualModulesPlugin.prototype.writeModule = function(filePath, contents) { - var len = contents ? contents.length : 0; - var time = new Date(); - var timeMs = time.getTime(); - - var stats = new VirtualStats({ - dev: 8675309, - ino: inode++, - mode: 33188, - nlink: 0, - uid: 1000, - gid: 1000, - rdev: 0, - size: len, - blksize: 4096, - blocks: Math.floor(len / 4096), - atimeMs: timeMs, - mtimeMs: timeMs, - ctimeMs: timeMs, - birthtimeMs: timeMs, - atime: time, - mtime: time, - ctime: time, - birthtime: time - }); - - this.compiler.inputFileSystem._writeVirtualFile(filePath, stats, contents); -}; - -function setData(storage, key, value) { - if (storage.data instanceof Map) { - storage.data.set(key, value); - } else { - storage.data[key] = value; - } -} - -module.exports = VirtualModulesPlugin; diff --git a/test/loader.spec.js b/test/loader.spec.js index e5366a9d..e9c40b49 100644 --- a/test/loader.spec.js +++ b/test/loader.spec.js @@ -216,7 +216,7 @@ describe('loader', () => { function(err, code, map) { expect(err).not.to.exist; - expect(code).to.match(/import '.+\.css';/); + expect(code).to.match(/!=!svelte-loader\?cssPath=/); }, { emitCss: true } )