Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhence the compatilbily of filename as Function, also using Entrypoint names as includes and groups #83

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
53 changes: 45 additions & 8 deletions src/loader.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/**
* The loader component is supposed to extract the media CSS from the source chunks.
* To do this it uses a custom PostCSS plugin.
* To do this it uses a custom PostCSS plugin.
* In the course of this the original media CSS gets removed.
*/

Expand All @@ -9,7 +9,7 @@ const postcss = require('postcss');
const store = require('./store');
const plugin = require('./postcss');

module.exports = function(source) {
module.exports = function (source) {

// make loader async
const cb = this.async();
Expand All @@ -24,20 +24,57 @@ module.exports = function(source) {
// (don't use options.filename to avoid name conflicts)
options.path = interpolateName(this, '[path][name].[ext]', {});


// get responding EntryPoint name
// for those using <Object> Entries
let webpackEntryPoint = '';
this._compilation.entries.forEach(entry => {
entry.dependencies.forEach(file => {

const FileEntry = file.request;
let FileEntry_Resolved = '';

if (FileEntry.startsWith("/") ||
(FileEntry.length > 1 && FileEntry[1] === ":")
) {
FileEntry_Resolved = FileEntry;
} else {
FileEntry_Resolved = this.rootContext + FileEntry.replace(/^.\//, '/');
}

if ('' == webpackEntryPoint && FileEntry_Resolved === options.path) {
webpackEntryPoint = entry.options.name;
}
});
});
options.entrypoint = webpackEntryPoint;


let isIncluded = false;

// check if current file should be affected
if (options.include instanceof Array && options.include.indexOf(options.basename) !== -1) {
isIncluded = true;
} else if (options.include instanceof RegExp && options.basename.match(options.include)) {
isIncluded = true;
} else if (options.include === true) {
if (options.include === true) {
isIncluded = true;
} else {
if (1 == Object.keys(this._compilation.entries).length) {
if (options.include instanceof Array && options.include.indexOf(options.basename) !== -1) {
isIncluded = true;
} else if (options.include instanceof RegExp && options.basename.match(options.include)) {
isIncluded = true;
}
}
else {
if (options.include instanceof Array && options.include.indexOf(options.entrypoint) !== -1) {
isIncluded = true;
} else if (options.include instanceof RegExp && options.entrypoint.match(options.include)) {
isIncluded = true;
}
}
}

// return (either modified or not) source
if (isIncluded === true) {
postcss([ plugin(options) ])
postcss([plugin(options)])
.process(source, { from: options.basename })
.then(result => {
cb(null, result.toString())
Expand Down
26 changes: 15 additions & 11 deletions src/plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,23 +67,13 @@ module.exports = class MediaQueryPlugin {

const chunks = compilation.chunks;
const chunkIds = [...chunks].map(chunk => chunk.id);
const assets = hasDeprecatedChunks ? compilation.assets : compilationAssets;
const assets = hasDeprecatedChunks ? compilation.assets : compilationAssets;

store.getMediaKeys().forEach(mediaKey => {

const css = store.getMedia(mediaKey);
const queries = store.getQueries(mediaKey);

// generate hash and use for [hash] within basename
const hash = interpolateName({}, `[hash:${compiler.options.output.hashDigestLength}]`, { content: css });

// compute basename according to filename option
// while considering hash
const basename = this.options.filename
.replace('[name]', mediaKey)
.replace(/\[(content|chunk)?hash\]/, hash)
.replace(/\.[^.]+$/, '');

// if there's no chunk for the extracted media, create one
if (chunkIds.indexOf(mediaKey) === -1) {
const mediaChunk = new Chunk(mediaKey);
Expand All @@ -105,6 +95,20 @@ module.exports = class MediaQueryPlugin {
chunk.query = queries[0];
}

// generate hash and use for [hash] within basename
const hash = interpolateName({}, `[hash:${compiler.options.output.hashDigestLength}]`, { content: css });

// compute basename according to filename option
// while considering hash
const filename = typeof this.options.filename == 'function'
? this.options.filename({ chunk })
: this.options.filename;

const basename = filename
.replace('[name]', mediaKey)
.replace(/\[(content|chunk)?hash\]/, hash)
.replace(/\.[^.]+$/, '');

// find existing js & css files of this chunk
let existingFiles = { js: [], css: [] };
[...chunk.files].forEach(file => {
Expand Down
6 changes: 3 additions & 3 deletions src/postcss.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ module.exports = postcss.plugin('MediaQueryPostCSS', options => {

const css = postcss.root().append(atRule).toString();
const query = atRule.params;

store.addMedia(name, css, options.path, query);
}

Expand Down Expand Up @@ -53,9 +53,9 @@ module.exports = postcss.plugin('MediaQueryPostCSS', options => {
const queryname = getQueryName(atRule.params);

if (queryname) {
const groupName = getGroupName(options.basename);
const groupName = (-1 !== ['', 'main'].indexOf(options.entrypoint)) ? getGroupName(options.basename) : getGroupName(options.entrypoint);
const name = groupName ? `${groupName}-${queryname}` : `${options.basename}-${queryname}`;

addToStore(name, atRule);
atRule.remove();
}
Expand Down