diff --git a/package-lock.json b/package-lock.json index 02bdaea..d28f5f1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2447,6 +2447,11 @@ "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", "dev": true }, + "buffer-json": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/buffer-json/-/buffer-json-2.0.0.tgz", + "integrity": "sha512-+jjPFVqyfF1esi9fvfUs3NqM0pH1ziZ36VP4hmA/y/Ssfo/5w5xHKfTw9BwQjoJ1w/oVtpLomqwUHKdefGyuHw==" + }, "buffer-xor": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", @@ -4827,6 +4832,16 @@ "object-assign": "^4.0.1" } }, + "file-loader": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-3.0.1.tgz", + "integrity": "sha512-4sNIOXgtH/9WZq4NvlfU3Opn5ynUsqBwSLyM+I7UOwdGigTBYfVVQEwe/msZNX/j4pCJTIM14Fsw66Svo1oVrw==", + "dev": true, + "requires": { + "loader-utils": "^1.0.2", + "schema-utils": "^1.0.0" + } + }, "fileset": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/fileset/-/fileset-2.0.3.tgz", diff --git a/package.json b/package.json index 887db7b..258df0d 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,7 @@ "webpack": "^4.0.0" }, "dependencies": { + "buffer-json": "^2.0.0", "find-cache-dir": "^2.1.0", "loader-utils": "^1.1.0", "mkdirp": "^0.5.1", @@ -64,6 +65,7 @@ "eslint-config-webpack": "^1.0.0", "eslint-plugin-import": "^2.0.0", "eslint-plugin-prettier": "^3.0.0", + "file-loader": "^3.0.1", "husky": "^1.2.1", "jest": "^24.5.0", "lint-staged": "^8.1.0", diff --git a/src/index.js b/src/index.js index bab5249..f6bf6e5 100644 --- a/src/index.js +++ b/src/index.js @@ -9,6 +9,7 @@ const async = require('neo-async'); const crypto = require('crypto'); const mkdirp = require('mkdirp'); const findCacheDir = require('find-cache-dir'); +const BJSON = require('buffer-json'); const { getOptions } = require('loader-utils'); const validateOptions = require('schema-utils'); @@ -211,7 +212,7 @@ const directories = new Set(); function write(key, data, callback) { const dirname = path.dirname(key); - const content = JSON.stringify(data); + const content = BJSON.stringify(data); if (directories.has(dirname)) { // for performance skip creating directory @@ -238,7 +239,7 @@ function read(key, callback) { } try { - const data = JSON.parse(content); + const data = BJSON.parse(content); callback(null, data); } catch (e) { callback(e); @@ -253,4 +254,5 @@ function cacheKey(options, request) { return path.join(cacheDirectory, `${hash}.json`); } +export const raw = true; export { loader as default, pitch }; diff --git a/test/__snapshots__/cacheContext-option.test.js.snap b/test/__snapshots__/cacheContext-option.test.js.snap index c3aead6..dec9806 100644 --- a/test/__snapshots__/cacheContext-option.test.js.snap +++ b/test/__snapshots__/cacheContext-option.test.js.snap @@ -7,68 +7,72 @@ exports[`cacheContext option should generate absolute paths to the project root: exports[`cacheContext option should generate relative paths to the project root: errors 1`] = `Array []`; exports[`cacheContext option should generate relative paths to the project root: generated cache-loader data 1`] = ` -Array [ - Object { - "contextDependencies": Array [], - "dependencies": Array [ - Object { - "mtime": null, - "path": "test/fixtures/basic/file_1.js", +"[ + { + \\"remainingRequest\\": \\"test/fixtures/basic/file_1.js\\", + \\"dependencies\\": [ + { + \\"path\\": \\"test/fixtures/basic/file_1.js\\", + \\"mtime\\": null }, - Object { - "mtime": null, - "path": "src/index.js", - }, - ], - "remainingRequest": "test/fixtures/basic/file_1.js", - "result": Array [ - "/* eslint-disable */ -console.log('file_1'); -", + { + \\"path\\": \\"src/index.js\\", + \\"mtime\\": null + } ], + \\"contextDependencies\\": [], + \\"result\\": [ + { + \\"type\\": \\"Buffer\\", + \\"data\\": \\"base64:LyogZXNsaW50LWRpc2FibGUgKi8KY29uc29sZS5sb2coJ2ZpbGVfMScpOwo=\\" + } + ] }, - Object { - "contextDependencies": Array [], - "dependencies": Array [ - Object { - "mtime": null, - "path": "test/fixtures/basic/file_2.js", - }, - Object { - "mtime": null, - "path": "src/index.js", + { + \\"remainingRequest\\": \\"test/fixtures/basic/file_2.js\\", + \\"dependencies\\": [ + { + \\"path\\": \\"test/fixtures/basic/file_2.js\\", + \\"mtime\\": null }, + { + \\"path\\": \\"src/index.js\\", + \\"mtime\\": null + } ], - "remainingRequest": "test/fixtures/basic/file_2.js", - "result": Array [ - "/* eslint-disable */ -console.log('file_2'); -", - ], + \\"contextDependencies\\": [], + \\"result\\": [ + { + \\"type\\": \\"Buffer\\", + \\"data\\": \\"base64:LyogZXNsaW50LWRpc2FibGUgKi8KY29uc29sZS5sb2coJ2ZpbGVfMicpOwo=\\" + } + ] }, - Object { - "contextDependencies": Array [], - "dependencies": Array [ - Object { - "mtime": null, - "path": "test/fixtures/basic/index.js", - }, - Object { - "mtime": null, - "path": "src/index.js", + { + \\"remainingRequest\\": \\"test/fixtures/basic/index.js\\", + \\"dependencies\\": [ + { + \\"path\\": \\"test/fixtures/basic/index.js\\", + \\"mtime\\": null }, + { + \\"path\\": \\"src/index.js\\", + \\"mtime\\": null + } ], - "remainingRequest": "test/fixtures/basic/index.js", - "result": Array [ - "/* eslint-disable */ -require('./file_1.js'); -require('./file_2.js'); - -console.log('basic_entry'); -", - ], - }, -] + \\"contextDependencies\\": [], + \\"result\\": [ + { + \\"type\\": \\"Buffer\\", + \\"data\\": \\"base64:LyogZXNsaW50LWRpc2FibGUgKi8KcmVxdWlyZSgnLi9maWxlXzEuanMnKTsKcmVxdWlyZSgnLi9maWxlXzIuanMnKTsKCmNvbnNvbGUubG9nKCdiYXNpY19lbnRyeScpOwo=\\" + } + ] + } +]" `; exports[`cacheContext option should generate relative paths to the project root: warnings 1`] = `Array []`; + +exports[`cacheContext option should load as a raw loader to support images: errors 1`] = `Array []`; + +exports[`cacheContext option should load as a raw loader to support images: warnings 1`] = `Array []`; diff --git a/test/cacheContext-option.test.js b/test/cacheContext-option.test.js index f41d818..4609187 100644 --- a/test/cacheContext-option.test.js +++ b/test/cacheContext-option.test.js @@ -1,6 +1,7 @@ const path = require('path'); const normalizePath = require('normalize-path'); +const BJSON = require('buffer-json'); const { webpack } = require('./helpers'); @@ -27,6 +28,18 @@ const mockRelativeWebpackConfig = { }, }; +const sortData = (a, b) => { + if (a.remainingRequest < b.remainingRequest) { + return -1; + } + + if (a.remainingRequest > b.remainingRequest) { + return 1; + } + + return 0; +}; + const buildSnapshotReadyDeps = (deps) => deps.map((dep) => Object.assign({}, dep, { mtime: null, path: dep.path })); @@ -46,19 +59,7 @@ const buildCacheLoaderCallsData = (calls) => }); }, new Map()) .values() - ); - -const sortData = (a, b) => { - if (a.remainingRequest < b.remainingRequest) { - return -1; - } - - if (a.remainingRequest > b.remainingRequest) { - return 1; - } - - return 0; -}; + ).sort(sortData); describe('cacheContext option', () => { it('should generate relative paths to the project root', async () => { @@ -67,14 +68,16 @@ describe('cacheContext option', () => { const cacheLoaderCallsData = buildCacheLoaderCallsData( mockCacheLoaderWriteFn.mock.calls - ).sort(sortData); + ); expect( cacheLoaderCallsData.every( (call) => !call.remainingRequest.includes(path.resolve('.')) ) + ).toBeTruthy(); + expect(BJSON.stringify(cacheLoaderCallsData, 2)).toMatchSnapshot( + 'generated cache-loader data' ); - expect(cacheLoaderCallsData).toMatchSnapshot('generated cache-loader data'); expect(stats.compilation.warnings).toMatchSnapshot('warnings'); expect(stats.compilation.errors).toMatchSnapshot('errors'); }); @@ -85,13 +88,13 @@ describe('cacheContext option', () => { const cacheLoaderCallsData = buildCacheLoaderCallsData( mockCacheLoaderWriteFn.mock.calls - ).sort(sortData); + ); expect( cacheLoaderCallsData.every( (call) => call.remainingRequest === normalizePath(call.remainingRequest) ) - ); + ).toBeTruthy(); }); it('should generate absolute paths to the project root', async () => { @@ -100,12 +103,27 @@ describe('cacheContext option', () => { const cacheLoaderCallsData = buildCacheLoaderCallsData( mockCacheLoaderWriteFn.mock.calls - ).sort(sortData); + ); expect( cacheLoaderCallsData.every((call) => call.remainingRequest.includes(path.resolve('.')) ) + ).toBeFalsy(); + expect(stats.compilation.warnings).toMatchSnapshot('warnings'); + expect(stats.compilation.errors).toMatchSnapshot('errors'); + }); + + it('should load as a raw loader to support images', async () => { + const testId = './img/index.js'; + const stats = await webpack(testId, mockBaseWebpackConfig); + + const cacheLoaderCallsData = buildCacheLoaderCallsData( + mockCacheLoaderWriteFn.mock.calls + ); + + expect( + cacheLoaderCallsData.every((call) => Buffer.isBuffer(call.result[0])) ); expect(stats.compilation.warnings).toMatchSnapshot('warnings'); expect(stats.compilation.errors).toMatchSnapshot('errors'); diff --git a/test/fixtures/img/index.js b/test/fixtures/img/index.js new file mode 100644 index 0000000..479e6a1 --- /dev/null +++ b/test/fixtures/img/index.js @@ -0,0 +1,4 @@ +/* eslint-disable */ +import png from '../img/webpack_logo.png'; + +console.log(png); diff --git a/test/fixtures/img/webpack_logo.png b/test/fixtures/img/webpack_logo.png new file mode 100644 index 0000000..68afbe1 Binary files /dev/null and b/test/fixtures/img/webpack_logo.png differ diff --git a/test/helpers.js b/test/helpers.js index b65d57a..7531e43 100644 --- a/test/helpers.js +++ b/test/helpers.js @@ -1,4 +1,5 @@ const path = require('path'); + const del = require('del'); const webpack = require('webpack'); const MemoryFS = require('memory-fs'); @@ -26,6 +27,16 @@ const moduleConfig = (config) => { : [] ), }, + { + test: /\.png$/, + use: [ + { + loader: path.resolve(__dirname, '../src/index.js'), + options: (config.loader && config.loader.options) || {}, + }, + 'file-loader', + ], + }, ], }; };