Skip to content

Commit da05f62

Browse files
author
jsilva work
committed
Initial Commit
0 parents  commit da05f62

39 files changed

+3890
-0
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
node_modules/
2+
coverage/lcov-report
3+
test/fixtures/**/dir
4+
.nyc_output/

LICENSE

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
The MIT License (MIT)
2+
Copyright (c) 2017 Jessica Silva
3+
4+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5+
6+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
7+
8+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

README.md

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
# Webpack Omit JS for CSS Plugin
2+
3+
This plugin will omit the JS files, for CSS only dependencies, that become obsolete once extract-text-plugin extracts all inlined CSS into its own .css file
4+
5+
## Rationale
6+
7+
In some cases, you may want to organize some of your CSS dependencies into single files or entry arrays within Webpack. Extract-text-plugin extracts the CSS into its own .css file, but Webpack will still generate a js file that will never be needed. This plugin will omit these types of files before Webpack begins it's emitting step. This plugin is especially useful for Webpack bundles that use a hash in the the filename, as these change on every compilation.
8+
9+
Example as a file
10+
```js
11+
// styles.js
12+
require('a.css');
13+
require('b.css');
14+
15+
// webpack.config.js
16+
module.exports = {
17+
entry: {
18+
'common.styles' : 'styles.js'
19+
}
20+
}
21+
// Webpack Output:
22+
// common.styles.js (Not Needed)
23+
// common.styles.css
24+
```
25+
NOTE: CSS dependencies in a JS file are 1 level deep. It will not recursively check for dependencies that are only CSS when requiring additional JS files.
26+
27+
Example as an array
28+
```js
29+
module.exports = {
30+
entry: {
31+
'common.styles' : [
32+
'a.css',
33+
'b.css'
34+
]
35+
}
36+
}
37+
// Webpack Output:
38+
// common.styles.js (Not Needed)
39+
// common.styles.css
40+
```
41+
42+
43+
## Installation
44+
```bash
45+
npm install --save-dev webpack-omit-js-for-css-plugin
46+
```
47+
## Usage
48+
49+
```js
50+
const OmitJSforCSSPlugin = require("webpack-omit-js-for-css-plugin");
51+
52+
module.exports = {
53+
plugins: [
54+
new OmitJSforCSSPlugin()
55+
]
56+
}
57+
```
58+
NOTE: [ExtractTextPlugin](https://github.com/webpack-contrib/extract-text-webpack-plugin "ExtractTextPlugin") is a Peer Dependency. You will need to configure that as you normally would in your webpack.config.js
59+
60+
## Options
61+
```js
62+
new OmitJSforCSSPlugin(options: object)
63+
```
64+
|Name|Type|Default|Description|
65+
|:--:|:--:|:-----:|:----------|
66+
|**`preview`**|`{Boolean}`|false|Will display a preview of the files that are to be omitted in the console (Will not actually omit)|
67+
|**`cacheOnWatch`**|`{Boolean}`|false|Whether it should cache the JS filenames that should be omitted, on watch|
68+
|**`verbose`**|`{Boolean}`|false|Whether it should display which files will be omitted to the console|
69+
70+
## Additional Notes
71+
Although, this plugin supports caching the omissable files on watch, ideally you shouldn't be using this plugin during Development. Rather, it is highly recommended that you only include this plugin when you are building for production.

coverage/lcov.info

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
TN:
2+
SF:/Users/jsilva/Documents/htdocs/webpack-omit-js-for-css-plugin/src/index.js
3+
FN:14,OmitJSforCSSPlugin
4+
FN:34,(anonymous_1)
5+
FN:48,(anonymous_2)
6+
FN:50,(anonymous_3)
7+
FN:55,(anonymous_4)
8+
FN:62,(anonymous_5)
9+
FN:66,(anonymous_6)
10+
FN:74,(anonymous_7)
11+
FN:95,(anonymous_8)
12+
FN:96,(anonymous_9)
13+
FN:99,(anonymous_10)
14+
FNF:11
15+
FNH:11
16+
FNDA:14,OmitJSforCSSPlugin
17+
FNDA:17,(anonymous_1)
18+
FNDA:12,(anonymous_2)
19+
FNDA:12,(anonymous_3)
20+
FNDA:12,(anonymous_4)
21+
FNDA:62,(anonymous_5)
22+
FNDA:185,(anonymous_6)
23+
FNDA:40,(anonymous_7)
24+
FNDA:13,(anonymous_8)
25+
FNDA:13,(anonymous_9)
26+
FNDA:2,(anonymous_10)
27+
DA:8,1
28+
DA:15,14
29+
DA:21,14
30+
DA:22,4
31+
DA:25,10
32+
DA:26,10
33+
DA:34,1
34+
DA:35,17
35+
DA:36,4
36+
DA:39,13
37+
DA:40,13
38+
DA:48,1
39+
DA:50,12
40+
DA:52,12
41+
DA:53,12
42+
DA:55,12
43+
DA:56,12
44+
DA:57,9
45+
DA:62,12
46+
DA:63,62
47+
DA:64,3
48+
DA:66,59
49+
DA:67,185
50+
DA:68,40
51+
DA:74,12
52+
DA:77,40
53+
DA:78,15
54+
DA:83,15
55+
DA:84,15
56+
DA:95,1
57+
DA:96,13
58+
DA:98,13
59+
DA:99,2
60+
DA:102,12
61+
DA:104,13
62+
DA:108,1
63+
LF:36
64+
LH:36
65+
BRDA:21,0,0,4
66+
BRDA:21,0,1,10
67+
BRDA:21,1,0,14
68+
BRDA:21,1,1,8
69+
BRDA:21,1,2,7
70+
BRDA:21,1,3,11
71+
BRDA:25,2,0,10
72+
BRDA:25,2,1,6
73+
BRDA:35,3,0,4
74+
BRDA:35,3,1,13
75+
BRDA:39,4,0,13
76+
BRDA:39,4,1,2
77+
BRDA:56,5,0,9
78+
BRDA:56,5,1,3
79+
BRDA:63,6,0,3
80+
BRDA:63,6,1,59
81+
BRDA:67,7,0,40
82+
BRDA:67,7,1,145
83+
BRDA:67,8,0,185
84+
BRDA:67,8,1,176
85+
BRDA:68,9,0,36
86+
BRDA:68,9,1,4
87+
BRDA:77,10,0,15
88+
BRDA:77,10,1,25
89+
BRDA:77,11,0,40
90+
BRDA:77,11,1,34
91+
BRDA:77,11,2,30
92+
BRDA:77,11,3,22
93+
BRDA:98,12,0,1
94+
BRDA:98,12,1,12
95+
BRDA:98,13,0,13
96+
BRDA:98,13,1,2
97+
BRF:32
98+
BRH:32
99+
end_of_record

package.json

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
{
2+
"name": "webpack-omit-js-for-css-plugin",
3+
"version": "0.1.0",
4+
"description": "This Webpack plugin will omit the JS files, for CSS only dependencies, that become obsolete once extract-text-plugin extracts all inlined CSS into its own .css file",
5+
"main": "src/index.js",
6+
"directories": {
7+
"test": "test"
8+
},
9+
"scripts": {
10+
"test": "mocha --timeout 10000 test/*.test.js",
11+
"watch:test": "mocha --timeout 10000 --watch test/*.test.js",
12+
"test:cover" : "nyc npm run test",
13+
"cover:lcovonly": "nyc report --reporter=lcovonly"
14+
},
15+
"keywords": [
16+
"webpack",
17+
"plugin",
18+
"extract-text-plugin",
19+
"omit-js-for-css-plugin",
20+
"omit js",
21+
"webpack omit",
22+
"css"
23+
],
24+
"author": "Jessica Silva",
25+
"license": "MIT",
26+
"peerDependencies": {
27+
"extract-text-webpack-plugin": "^2.1.0",
28+
"webpack": "^2.2.0"
29+
},
30+
"devDependencies": {
31+
"chai": "^3.5.0",
32+
"css-loader": "^0.27.3",
33+
"extract-text-webpack-plugin": "^2.1.0",
34+
"mocha": "^3.2.0",
35+
"nyc": "^10.2.0",
36+
"rimraf": "^2.6.1",
37+
"style-loader": "^0.13.2",
38+
"test-console": "^1.0.0",
39+
"webpack": "^2.3.3"
40+
},
41+
"dependencies": {
42+
"chalk": "^1.1.3"
43+
},
44+
"nyc": {
45+
"include": [
46+
"src/**.js"
47+
],
48+
"reporter" : [
49+
"text",
50+
"lcov"
51+
],
52+
"check-coverage": true,
53+
"branches": 100,
54+
"functions": 100,
55+
"lines": 100,
56+
"statements": 100
57+
}
58+
}

src/index.js

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
/**
2+
* OmitJSforCSSPlugin
3+
* @description : This plugin will omit the JS entry files, for CSS only dependencies, that become obsolete once extract-text-plugin extracts all inlined CSS into its own .css file.
4+
*/
5+
6+
const chalk = require('chalk');
7+
8+
/**
9+
* @param {Object} options - Configurable options
10+
* @constructor
11+
*/
12+
function OmitJSforCSSPlugin(options) {
13+
const defaults = {
14+
preview : false, // OPTIONAL - {Boolean} - A preview of the files that are to be omitted (Will not actually omit)
15+
cacheOnWatch : false, // OPTIONAL - {Boolean} - Whether it should cache the JS filenames that should be omitted on watch
16+
verbose : false // OPTIONAL - {Boolean} - Whether it should display which files will be omitted
17+
};
18+
19+
if(typeof options !== "undefined" && (options === null || typeof options !== "object") || Array.isArray(options)){
20+
throw new Error('OmitJSforCSSPlugin only takes an options "object" as an argument');
21+
}
22+
23+
this.options = Object.assign({}, defaults, options || {});
24+
this.cacheOmittedFilename = [];
25+
};
26+
27+
/**
28+
* @function omitFiles
29+
* @param {Object} omitted - The omitted file's details
30+
* @param {Object} compilation
31+
*/
32+
OmitJSforCSSPlugin.prototype.omitFiles = function(omitted, compilation){
33+
if(this.options.preview){
34+
console.log(chalk.bold(chalk.red('PREVIEW')) + chalk.grey(' File to be omitted for ')+ chalk.bold(chalk.green(omitted.chunkName)) +' : ' + chalk.bold(chalk.green(omitted.filename)));
35+
}
36+
else {
37+
this.options.verbose && console.log(chalk.grey('File Omitted for ')+ chalk.bold(chalk.green(omitted.chunkName)) + chalk.grey(' : ') + chalk.bold(chalk.green(omitted.filename)));
38+
delete compilation.assets[omitted.filename];
39+
}
40+
};
41+
42+
/**
43+
* @function findOmissibleFiles
44+
* @param {Object} compilation
45+
*/
46+
OmitJSforCSSPlugin.prototype.findOmissibleFiles = function(compilation){
47+
// For every chunk / entry point figure out if its all CSS based
48+
compilation.chunks.forEach((chunk) => {
49+
// Chunks origin files. ex. origin entry point, ![] entry
50+
let resourceOrigin = {};
51+
let assetTypeCount = { internal : 0, css : 0 };
52+
53+
chunk.origins.forEach((origin) => {
54+
if(typeof origin.module.resource === "string") {
55+
resourceOrigin[origin.module.resource] = true;
56+
}
57+
});
58+
59+
// Each entry point will have its own dependencies, based on the files inner deps or the array deps in entry
60+
chunk.modules.forEach((module) => {
61+
if(!Array.isArray(module.fileDependencies)){
62+
return;
63+
}
64+
module.fileDependencies.forEach((filepath) => {
65+
if(!resourceOrigin[filepath] && !(/(\bnode_modules\b)/).test(filepath)) {
66+
(/\.(css)$/i).test(filepath) ? assetTypeCount.css++ : assetTypeCount.internal++;
67+
}
68+
});
69+
});
70+
71+
// Get the filenames that will be emitted, generated by the chunk, and omit JS if applicable
72+
chunk.files.forEach((filename) => {
73+
// If all dependencies of this entry were CSS, then a JS version of this file will be created
74+
// This js file will be empty due to extract-text-webpack-plugin
75+
if((assetTypeCount.css > 0 && assetTypeCount.internal === 0) && ((/\.(js)$/i).test(filename) || (/\.(js).map$/i).test(filename))){
76+
let omitted = {
77+
'filename' : filename,
78+
'chunkName' : chunk.name
79+
};
80+
81+
this.cacheOmittedFilename.push(omitted);
82+
this.omitFiles(omitted, compilation);
83+
}
84+
});
85+
86+
});
87+
};
88+
89+
/**
90+
* Hook into the webpack compiler
91+
* @param {Object} compiler - The webpack compiler object
92+
*/
93+
OmitJSforCSSPlugin.prototype.apply = function(compiler) {
94+
compiler.plugin('emit', (compilation, callback) => {
95+
96+
if(this.options.cacheOnWatch && this.cacheOmittedFilename.length){
97+
this.cacheOmittedFilename.forEach((omitted) => { this.omitFiles(omitted, compilation) });
98+
}
99+
else {
100+
this.findOmissibleFiles(compilation);
101+
}
102+
callback();
103+
});
104+
};
105+
106+
module.exports = OmitJSforCSSPlugin;

test/css-entry-array.test.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
const webpack = require('webpack');
2+
const expect = require('chai').expect;
3+
const path = require('path');
4+
const rimraf = require('rimraf');
5+
const options = require('./fixtures/css-array-entry/webpack.config.js');
6+
const dirPath = path.join(__dirname, './fixtures/css-array-entry/dir');
7+
const fileShouldNotExist = require('./utils/file-should-not-exist.js');
8+
9+
describe('Array of CSS Dependencies as Entry', () => {
10+
before((done) => {
11+
rimraf(dirPath, () => {
12+
done();
13+
});
14+
});
15+
16+
it('JS entry should not exist', (done) => {
17+
webpack(options, () => {
18+
fileShouldNotExist(dirPath, '/a.js');
19+
done();
20+
});
21+
});
22+
23+
it('JS entry source map should not exist', (done) => {
24+
var optionSourceMap = Object.assign({}, options);
25+
optionSourceMap.devtool = 'source-map';
26+
27+
webpack(optionSourceMap, () => {
28+
fileShouldNotExist(dirPath, '/a.js.map');
29+
done();
30+
});
31+
});
32+
});
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.one { color : red; }
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.two { color : blue; }

0 commit comments

Comments
 (0)