Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 13 additions & 15 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,27 @@

const path = require('path');
const fs = require('fs');
const loaderUtils = require('loader-utils');
const transform = require('./transform');

function ChunkHashReplacePlugin(options) {
this.src = options.src;
this.dest = options.dest;
}
class ChunkHashReplacePlugin {
constructor(options) {
this.src = options.src;
this.dest = options.dest;
}

ChunkHashReplacePlugin.prototype.apply = function (compiler) {
const self = this;
const folder = compiler.options.context;
const src = path.join(folder, self.src);
const dest = path.join(folder, self.dest);
const cssFilePaths = self.cssFilePaths;
apply(compiler) {
const self = this;
const folder = compiler.options.context;
const src = path.join(folder, self.src);
const dest = path.join(folder, self.dest);

fs.readFile(src, 'utf8', function (err, data) {
compiler.plugin('done', function (statsData) {
compiler.hooks.done.tap('ChunkHashReplacePlugin', (statsData) => {
const stats = statsData.toJson();
const template = fs.readFileSync(src, 'utf8');
const htmlOutput = transform(template, stats.chunks);
fs.writeFileSync(dest, htmlOutput);
});
});
};
}
}

module.exports = ChunkHashReplacePlugin;
50 changes: 42 additions & 8 deletions test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,20 @@ const transform = require('./transform');
const assert = require('assert');

describe('ChunkHashReplacePlugin', () => {
it('should transform single js bundle', function () {
it('should transform single js bundle', () => {
const appBundle = 'app';
const appHash = '11111';
const appFile = `${appBundle}.${appHash}.js`;
const chunks = [{ files: [appFile], hash: appHash }]

const html = `<script src="${appBundle}.js"></script>`;
assert.equal(transform(html, chunks), `<script src="${appFile}"></script>`);
const transformedHtml = transform(html, chunks);
const expectedOutput = `<script src="${appFile}"></script>`;

assert.equal(transformedHtml, expectedOutput);
});

it('should transform multiple js bundles', function () {
it('should transform multiple js bundles', () => {
const appBundle = 'app';
const appHash = '11111';
const appFile = `${appBundle}.${appHash}.js`;
Expand All @@ -25,25 +29,55 @@ describe('ChunkHashReplacePlugin', () => {
]

const html = `<script src="${appBundle}.js"></script><script src="${vendorBundle}.js"></script>`;
const transformedHtml = transform(html, chunks);
const expectedOutput = `<script src="${appFile}"></script><script src="${vendorFile}"></script>`;

assert.equal(transform(html, chunks), `<script src="${appFile}"></script><script src="${vendorFile}"></script>`);
assert.equal(transformedHtml, expectedOutput);
});

it('should transform css bundle', function () {
it('should transform css bundle', () => {
const stylesBundle = 'app';
const stylesHash = '11111';
const stylesFile = `${stylesBundle}.${stylesHash}.css`;
const chunks = [{ files: [stylesFile], hash: stylesHash }]

const html = `<link href="${stylesBundle}.css" rel="stylesheet">`;
assert.equal(transform(html, chunks), `<link href="${stylesFile}" rel="stylesheet">`);
const transformedHtml = transform(html, chunks);
const expectedOutput = `<link href="${stylesFile}" rel="stylesheet">`;

assert.equal(transformedHtml, expectedOutput);
});

it('should transform bundles with underscores in name', function () {
it('should transform bundles with underscores in name', () => {
const appBundle = 'app_bundle';
const appHash = '11111';
const appFile = `${appBundle}.${appHash}.js`;
const chunks = [{ files: [appFile], hash: appHash }]

const html = `<script src="${appBundle}.js"></script>`;
assert.equal(transform(html, chunks), `<script src="${appFile}"></script>`);
const transformedHtml = transform(html, chunks);
const expectedOutput = `<script src="${appFile}"></script>`;

assert.equal(transformedHtml, expectedOutput);
});

it(`should transform multiple js bundles where one's name is same as the end of the other's hash`, function () {
const app1Bundle = 'foo';
const app1Hash = '321'; // last digit is 1
const app1File = `${app1Bundle}.${app1Hash}.js`;
const app2Bundle = '1'; // same as last digit of app1Hash
const app2Hash = 'zzzz';
const app2File = `${app2Bundle}.${app2Hash}.js`;

const chunks = [
{ files: [app1File], hash: app1Hash },
{ files: [app2File], hash: app2Hash }
]

const html = `<script src="${app1Bundle}.js"></script>`;
const transformedHtml = transform(html, chunks);
const expectedOutput = `<script src="${app1File}"></script>`;

assert.equal(transformedHtml, expectedOutput);
});
});
8 changes: 5 additions & 3 deletions transform.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,20 @@ function transform(template, chunks) {
let regex = null;
switch (extension) {
case 'js': {
regex = new RegExp(`(src=["'].*/)(${fileName}\\.js)(["'])`, 'i');
regex = new RegExp(`(src=["'])([^'"]+/)?(${fileName}\.js)(["'])`, 'i');
break;
}
case 'css': {
regex = new RegExp(`(href=["'].*/)(${fileName}\\.css)(["'])`, 'i');
regex = new RegExp(`(href=["'])([^'"]+/)?(${fileName}\.css)(["'])`, 'i');
break;
}
default:
continue;
}

htmlOutput = htmlOutput.replace(regex, `$1${file}$3`);
htmlOutput = htmlOutput.replace(regex, (__match, p1, p2, __p3, p4) => {
return `${p1}${p2 || ""}${file}${p4}`;
});
}
}

Expand Down