Skip to content
This repository has been archived by the owner on May 29, 2019. It is now read-only.

refractor filename modify logic #423

Merged
merged 14 commits into from
Feb 26, 2017
25 changes: 24 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ new ExtractTextPlugin(options: filename | object)
|Name|Type|Description|
|:--:|:--:|:----------|
|**`id`**|`{String}`|Unique ident for this plugin instance. (For advanced usage only, by default automatically generated)|
|**`filename`**|`{String}`|Name of the result file. May contain `[name]`, `[id]` and `[contenthash]`|
|**`filename`**|`{String|Object}`|Name of the result file. May contain `[name]`, `[id]` and `[contenthash]`|
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It could accept a function directly instead of an object. The function would return a filename and allow you modify it. Simpler API/design.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also have to pass filename format like [name].css. Is is possible to do that via a function?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can return a pattern and it will work like before. You can do filename: file => '[name].css' in this design too. And access to the file parameter gives you flexibility for custom logic.

Copy link
Contributor Author

@lcxfs1991 lcxfs1991 Feb 21, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you add js/a as the entry key, webpack will replace [name] with css/js/a and it leaves no room for developers to do the following action:

filename.replace('js/css', 'css');

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can try my test case:

test/cases/multiple-entries-filename/webpack.config.js

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. It's that compilation.getPath which is the problem. Basically modify triggers after that.

The design could be inverted like this:

filename: (getPath, filename) => getPath(filename)

That getPath would run compilation.getPath with all its parameters and provide the hook that would give you maximum amount of control. Now you could manipulate filename before and after placeholders get applied while keeping the API surface minimal.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Expose getPath is cool too.

let me retune it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

look good?

extra

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I'll have a closer look in a bit. 👍

|**`allChunks`**|`{Boolean}`|Extract from all additional chunks too (by default it extracts only from the initial chunk(s))|
|**`disable`**|`{Boolean}`|Disables the plugin|
|**`ignoreOrder`**|`{Boolean}`|Disables order check (useful for CSS Modules!), `false` by default|
Expand Down Expand Up @@ -155,6 +155,29 @@ module.exports = {
}
```

### Modify filename

`filename` paramter could be `Object`. It accepts `format` and `modify` callback as attributes.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/s/paramter/parameter

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what does that mean?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a typo.

In the following config, before `modify` callback is called, the css path would be `css/js/a.css`.
After `modify` callback, it is transformed to `css/a.css`.

```js
entry: {
'js/a': "./a"
},
plugins: [
new ExtractTextPlugin({
filename: {
format: 'css/[name].css',
modify: (filename) => {
return filename.replace('css/js', 'css');
}
},
allChunks: true
})
]
```

<h2 align="center">Maintainer</h2>

<table>
Expand Down
26 changes: 25 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,18 @@ function isString(a) {
return typeof a === "string";
}

function isObject(a) {
return isType('Object', a);
}

function isFunction(a) {
return isType('Function', a);
}

function isType(type, obj) {
return Object.prototype.toString.call(obj) === '[object ' + type + ']';
}

ExtractTextPlugin.loader = function(options) {
return { loader: require.resolve("./loader"), options: options };
};
Expand Down Expand Up @@ -317,11 +329,23 @@ ExtractTextPlugin.prototype.apply = function(compiler) {
});
var chunk = extractedChunk.originalChunk;
var source = this.renderExtractedChunk(extractedChunk);
var file = compilation.getPath(filename, {

var format = filename;

if (isObject(filename)) {
format = filename.format;
}

var file = compilation.getPath(format, {
chunk: chunk
}).replace(/\[(?:(\w+):)?contenthash(?::([a-z]+\d*))?(?::(\d+))?\]/ig, function() {
return loaderUtils.getHashDigest(source.source(), arguments[1], arguments[2], parseInt(arguments[3], 10));
});

if (isFunction(filename.modify)) {
file = filename.modify(file);
}

compilation.assets[file] = source;
chunk.files.push(file);
}
Expand Down
5 changes: 4 additions & 1 deletion schema/plugin-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@
},
"filename": {
"description": "The filename and path that ExtractTextPlugin will extract to",
"type": "string"
"modes": {
"type": "string",
"type": "object"
}
},
"ignoreOrder": {
"description": "Ignore dependency order (useful for CSS Modules)",
Expand Down
4 changes: 4 additions & 0 deletions test/cases/multiple-entries-filename/a.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
require.ensure([], function() {
require("./a.txt");
require("./b.txt");
});
1 change: 1 addition & 0 deletions test/cases/multiple-entries-filename/a.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
a
4 changes: 4 additions & 0 deletions test/cases/multiple-entries-filename/b.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
require.ensure([], function() {
require("./a.txt");
require("./c.txt");
});
1 change: 1 addition & 0 deletions test/cases/multiple-entries-filename/b.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
b
1 change: 1 addition & 0 deletions test/cases/multiple-entries-filename/c.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
c
Binary file not shown.
2 changes: 2 additions & 0 deletions test/cases/multiple-entries-filename/expected/txt/a.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
a
b
2 changes: 2 additions & 0 deletions test/cases/multiple-entries-filename/expected/txt/b.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
a
c
18 changes: 18 additions & 0 deletions test/cases/multiple-entries-filename/webpack.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
var ExtractTextPlugin = require("../../../");
module.exports = {
entry: {
'js/a': "./a",
'js/b': "./b"
},
plugins: [
new ExtractTextPlugin({
filename: {
format: 'txt/[name].txt',
modify: (filename) => {
return filename.replace('txt/js', 'txt');
}
},
allChunks: true
})
]
};