Skip to content

Commit

Permalink
feat(webpack@5): improve stats for copied assets
Browse files Browse the repository at this point in the history
  • Loading branch information
evilebottnawi committed Aug 31, 2020
1 parent d8b4a72 commit 09b1dc9
Show file tree
Hide file tree
Showing 8 changed files with 1,067 additions and 1,697 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/nodejs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ jobs:
- name: Lint
run: npm run lint

# - name: Security audit
# run: npm run security
- name: Security audit
run: npm run security

- name: Check commit message
uses: wagoid/commitlint-github-action@v1
Expand Down
2,549 changes: 906 additions & 1,643 deletions package-lock.json

Large diffs are not rendered by default.

18 changes: 9 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,35 +49,35 @@
"loader-utils": "^2.0.0",
"normalize-path": "^3.0.0",
"p-limit": "^3.0.2",
"schema-utils": "^2.7.0",
"schema-utils": "^2.7.1",
"serialize-javascript": "^4.0.0",
"webpack-sources": "^1.4.3"
},
"devDependencies": {
"@babel/cli": "^7.10.5",
"@babel/core": "^7.11.1",
"@babel/core": "^7.11.4",
"@babel/preset-env": "^7.11.0",
"@commitlint/cli": "^9.1.1",
"@commitlint/config-conventional": "^9.1.1",
"@commitlint/cli": "^10.0.0",
"@commitlint/config-conventional": "^10.0.0",
"@webpack-contrib/defaults": "^6.3.0",
"@webpack-contrib/eslint-config-webpack": "^3.0.0",
"babel-jest": "^26.3.0",
"chokidar": "^3.4.2",
"cross-env": "^7.0.2",
"del": "^5.1.0",
"del-cli": "^3.0.1",
"eslint": "^7.6.0",
"eslint": "^7.7.0",
"eslint-config-prettier": "^6.11.0",
"eslint-plugin-import": "^2.22.0",
"husky": "^4.2.5",
"is-gzip": "^2.0.0",
"jest": "^26.3.0",
"lint-staged": "^10.2.11",
"jest": "^26.4.2",
"lint-staged": "^10.2.13",
"memfs": "^3.2.0",
"mkdirp": "^1.0.4",
"npm-run-all": "^4.1.5",
"prettier": "^2.0.5",
"standard-version": "^8.0.2",
"prettier": "^2.1.1",
"standard-version": "^9.0.0",
"webpack": "^4.44.1"
},
"keywords": [
Expand Down
23 changes: 18 additions & 5 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ class CopyPlugin {
}

apply(compiler) {
const plugin = { name: 'CopyPlugin' };
const pluginName = this.constructor.name;
const limit = pLimit(this.options.concurrency || 100);

compiler.hooks.thisCompilation.tap(plugin, (compilation) => {
compiler.hooks.thisCompilation.tap(pluginName, (compilation) => {
const logger = compilation.getLogger('copy-webpack-plugin');

compilation.hooks.additionalAssets.tapAsync(
Expand Down Expand Up @@ -110,13 +110,15 @@ class CopyPlugin {
return;
}

if (compilation.getAsset(targetPath)) {
const info = compilation.getAsset(targetPath);

if (info) {
if (force) {
logger.log(
`force updating '${webpackTo}' to compilation assets from '${absoluteFrom}'`
);

compilation.updateAsset(targetPath, source);
compilation.updateAsset(targetPath, source, { copied: true });

return;
}
Expand All @@ -132,14 +134,25 @@ class CopyPlugin {
`writing '${webpackTo}' to compilation assets from '${absoluteFrom}'`
);

compilation.emitAsset(targetPath, source);
compilation.emitAsset(targetPath, source, { copied: true });
});

logger.debug('end to adding additional assets');

callback();
}
);

if (compilation.hooks.statsPrinter) {
compilation.hooks.statsPrinter.tap(pluginName, (stats) => {
stats.hooks.print
.for('asset.info.copied')
.tap('copy-webpack-plugin', (copied, { green, formatFlag }) =>
// eslint-disable-next-line no-undefined
copied ? green(formatFlag('copied')) : undefined
);
});
}
});
}
}
Expand Down
78 changes: 78 additions & 0 deletions test/CopyPlugin.test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import path from 'path';

import webpack from 'webpack';

import CopyPlugin from '../src';

import { run, runEmit, runChange } from './helpers/run';
Expand Down Expand Up @@ -257,6 +259,82 @@ describe('CopyPlugin', () => {
.then(done)
.catch(done);
});

it('should copy files with "copied" flags', (done) => {
expect.assertions(5);

const expectedAssetKeys = [
'.dottedfile',
'directoryfile.txt',
'nested/deep-nested/deepnested.txt',
'nested/nestedfile.txt',
];

run({
preCopy: {
additionalAssets: [
{ name: 'foo-bar.txt', data: 'Content', info: { custom: true } },
{
name: 'nested/nestedfile.txt',
data: 'Content',
info: { custom: true },
},
],
},
expectedAssetKeys,
patterns: [
{
from: 'directory',
force: true,
},
],
})
.then(({ stats }) => {
for (const name of expectedAssetKeys) {
const info = stats.compilation.assetsInfo.get(name);

expect(info.copied).toBe(true);

if (name === 'nested/nestedfile.txt') {
expect(info.custom).toBe(true);
}
}
})
.then(done)
.catch(done);
});

it('should copy files and print "copied" in the string representation ', (done) => {
const isWebpack4 = webpack.version[0] === '4';

expect.assertions(isWebpack4 ? 0 : 1);

const expectedAssetKeys = [
'.dottedfile',
'directoryfile.txt',
'nested/deep-nested/deepnested.txt',
'nested/nestedfile.txt',
];

run({
withExistingAsset: true,
expectedAssetKeys,
patterns: [
{
from: 'directory',
},
],
})
.then(({ stats }) => {
const stringStats = stats.toString();

if (!isWebpack4) {
expect(stringStats.match(/\[copied]/g).length).toBe(4);
}
})
.then(done)
.catch(done);
});
});

describe('watch mode', () => {
Expand Down
69 changes: 39 additions & 30 deletions test/force-option.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ describe('force option', () => {
describe('is not specified', () => {
it('should not overwrite a file already in the compilation by default when "from" is a file', (done) => {
runForce({
existingAssets: ['file.txt'],
additionalAssets: [{ name: 'file.txt', data: 'existing' }],
expectedAssetKeys: ['file.txt'],
expectedAssetContent: {
'file.txt': 'existing',
Expand All @@ -21,11 +21,11 @@ describe('force option', () => {

it('should not overwrite files already in the compilation when "from" is a directory', (done) => {
runForce({
existingAssets: [
'.dottedfile',
'directoryfile.txt',
'nested/deep-nested/deepnested.txt',
'nested/nestedfile.txt',
additionalAssets: [
{ name: '.dottedfile', data: 'existing' },
{ name: 'directoryfile.txt', data: 'existing' },
{ name: 'nested/deep-nested/deepnested.txt', data: 'existing' },
{ name: 'nested/nestedfile.txt', data: 'existing' },
],
expectedAssetKeys: [
'.dottedfile',
Expand All @@ -51,10 +51,13 @@ describe('force option', () => {

it('should not overwrite files already in the compilation when "from" is a glob', (done) => {
runForce({
existingAssets: [
'directory/directoryfile.txt',
'directory/nested/deep-nested/deepnested.txt',
'directory/nested/nestedfile.txt',
additionalAssets: [
{ name: 'directory/directoryfile.txt', data: 'existing' },
{
name: 'directory/nested/deep-nested/deepnested.txt',
data: 'existing',
},
{ name: 'directory/nested/nestedfile.txt', data: 'existing' },
],
expectedAssetKeys: [
'directory/directoryfile.txt',
Expand All @@ -80,7 +83,7 @@ describe('force option', () => {
describe('is "false" (Boolean)', () => {
it('should not overwrite a file already in the compilation by default when "from" is a file', (done) => {
runForce({
existingAssets: ['file.txt'],
additionalAssets: [{ name: 'file.txt', data: 'existing' }],
expectedAssetKeys: ['file.txt'],
expectedAssetContent: {
'file.txt': 'existing',
Expand All @@ -98,11 +101,11 @@ describe('force option', () => {

it('should not overwrite files already in the compilation when "from" is a directory', (done) => {
runForce({
existingAssets: [
'.dottedfile',
'directoryfile.txt',
'nested/deep-nested/deepnested.txt',
'nested/nestedfile.txt',
additionalAssets: [
{ name: '.dottedfile', data: 'existing' },
{ name: 'directoryfile.txt', data: 'existing' },
{ name: 'nested/deep-nested/deepnested.txt', data: 'existing' },
{ name: 'nested/nestedfile.txt', data: 'existing' },
],
expectedAssetKeys: [
'.dottedfile',
Expand All @@ -129,10 +132,13 @@ describe('force option', () => {

it('should not overwrite files already in the compilation when "from" is a glob', (done) => {
runForce({
existingAssets: [
'directory/directoryfile.txt',
'directory/nested/deep-nested/deepnested.txt',
'directory/nested/nestedfile.txt',
additionalAssets: [
{ name: 'directory/directoryfile.txt', data: 'existing' },
{
name: 'directory/nested/deep-nested/deepnested.txt',
data: 'existing',
},
{ name: 'directory/nested/nestedfile.txt', data: 'existing' },
],
expectedAssetKeys: [
'directory/directoryfile.txt',
Expand All @@ -159,7 +165,7 @@ describe('force option', () => {
describe('is "true" (Boolean)', () => {
it('should force overwrite a file already in the compilation when "from" is a file', (done) => {
runForce({
existingAssets: ['file.txt'],
additionalAssets: [{ name: 'file.txt', data: 'existing' }],
expectedAssetKeys: ['file.txt'],
expectedAssetContent: {
'file.txt': 'new',
Expand All @@ -177,11 +183,11 @@ describe('force option', () => {

it('should force overwrite files already in the compilation when "from" is a directory', (done) => {
runForce({
existingAssets: [
'.dottedfile',
'directoryfile.txt',
'nested/deep-nested/deepnested.txt',
'nested/nestedfile.txt',
additionalAssets: [
{ name: '.dottedfile', data: 'existing' },
{ name: 'directoryfile.txt', data: 'existing' },
{ name: 'nested/deep-nested/deepnested.txt', data: 'existing' },
{ name: 'nested/nestedfile.txt', data: 'existing' },
],
expectedAssetKeys: [
'.dottedfile',
Expand All @@ -208,10 +214,13 @@ describe('force option', () => {

it('should force overwrite files already in the compilation when "from" is a glob', (done) => {
runForce({
existingAssets: [
'directory/directoryfile.txt',
'directory/nested/deep-nested/deepnested.txt',
'directory/nested/nestedfile.txt',
additionalAssets: [
{ name: 'directory/directoryfile.txt', data: 'existing' },
{
name: 'directory/nested/deep-nested/deepnested.txt',
data: 'existing',
},
{ name: 'directory/nested/nestedfile.txt', data: 'existing' },
],
expectedAssetKeys: [
'directory/directoryfile.txt',
Expand Down
19 changes: 11 additions & 8 deletions test/helpers/PreCopyPlugin.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
import webpack from 'webpack';

const { RawSource } =
// eslint-disable-next-line global-require
webpack.sources || require('webpack-sources');

class PreCopyPlugin {
constructor(options = {}) {
this.options = options.options || {};
Expand All @@ -8,15 +14,12 @@ class PreCopyPlugin {

compiler.hooks.thisCompilation.tap(plugin, (compilation) => {
compilation.hooks.additionalAssets.tapAsync(
'copy-webpack-plugin',
'pre-copy-webpack-plugin',
(callback) => {
this.options.existingAssets.forEach((assetName) => {
// eslint-disable-next-line no-param-reassign
compilation.assets[assetName] = {
source() {
return 'existing';
},
};
this.options.additionalAssets.forEach(({ name, data, info }) => {
const source = new RawSource(data);

compilation.emitAsset(name, source, info);
});

callback();
Expand Down
4 changes: 4 additions & 0 deletions test/helpers/run.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ function run(opts) {

const compiler = opts.compiler || getCompiler();

if (opts.preCopy) {
new PreCopyPlugin({ options: opts.preCopy }).apply(compiler);
}

new CopyPlugin({ patterns: opts.patterns, options: opts.options }).apply(
compiler
);
Expand Down

0 comments on commit 09b1dc9

Please sign in to comment.