ë¡ëë í¨ì를 ë´ë³´ë´ë ìë°ì¤í¬ë¦½í¸ 모ëì
ëë¤. ë¡ë ë¬ëë ì´ í¨ì를 í¸ì¶íì¬ ì´ì ë¡ë í¹ì 리ìì¤ íì¼ì 결과를 ì ë¬í©ëë¤. í¨ìì this 컨í
ì¤í¸ë webpackê³¼ ë¡ë ë¬ëì ìí´ ì±ìì§ë©°, ë¡ëê° í¸ì¶ì¤íì¼ì ë¹ëê¸°ë¡ ë³ê²½íê±°ë 쿼리 매ê°ë³ì를 ê°ì ¸ì¬ ì ìëë¡ íë ëªê°ì§ ì ì©í ë©ìë를 ì ê³µí©ëë¤.
첫 ë²ì§¸ ë¡ëìë 리ìì¤ íì¼ì ë´ì©ì´ë¼ë íëì ì¸ì를 ëê¹ëë¤. ì»´íì¼ë¬ë ë§ì§ë§ ë¡ëì 결과를 기ëí©ëë¤. ê²°ê³¼ë 모ëì ìë°ì¤í¬ë¦½í¸ ìì¤ ì½ë를 ëíë´ë String ëë Buffer(문ìì´ë¡ ë³íë¨)ì¬ì¼ í©ëë¤. ì íì ìì¤ë§µ ê²°ê³¼(JSON ê°ì²´ë¡)ë ì ë¬í ì ììµëë¤.
ë기 모ëììë ë¨ì¼ ê²°ê³¼ê° ë°íë ì ììµëë¤. ì¬ë¬ ê²°ê³¼ì ê²½ì° this.callback()ì í¸ì¶í´ì¼ íë©° ë¡ëë undefined를 ë°íí´ì¼ í©ëë¤.
ë¹ë기 모ëìì ë¹ë기 í¨ììì ë¨ì¼ 결과를 ë°íí ì ììµëë¤. ëë this.async()를 í¸ì¶íì¬ ë¡ë ë¬ëê° ë¹ë기 결과를 기ë¤ë ¤ì¼ í¨ì ëíë¼ ì ììµëë¤. ì´ ê²½ì° this.callback()ì ë°íí©ëë¤. ì´ ê²½ì° ë¡ëë undefined를 ë°ííê³ í´ë¹ ì½ë°±ì í¸ì¶í´ì¼ í©ëë¤. ì´ ìµì
ì ì¬ë¬ ê²°ê³¼ì ëí ì ì¼í ìµì
ì
ëë¤.
/**
*
* @param {string|Buffer} [content] 리ìì¤ íì¼ì ë´ì©
* @param {object} [map] https://github.com/mozilla/source-map ìì ì¬ì©í ì ìë ìì¤ë§µ ë°ì´í°
* @param {any} [meta] ë©í ë°ì´í°, 무ìì´ë ë ì ììµëë¤
*/
function webpackLoader(content, map, meta) {
// webpack ë¡ëì ì½ë
}ë¤ì ì¹ì
ììë ë¤ìí ì íì ë¡ëì ëí ëª ê°ì§ 기본 ì를 ì ê³µí©ëë¤. map ë° meta 매ê°ë³ìë ì í ì¬íì
ëë¤. ìëì this.callbackì ì°¸ê³ íì¸ì.
return ëë this.callbackì ì¬ì©íì¬ ë³íë content를 ë기ì ì¼ë¡ ë°íí ì ììµëë¤.
sync-loader.js
module.exports = function (content, map, meta) {
return someSyncOperation(content);
};this.callback ë©ìëë contentë§ ì¬ì©íë ê²ì´ ìëë¼ ì¬ë¬ ì¸ì를 ì ë¬í ì ìì¼ë¯ë¡ ë ì ì°í©ëë¤.
sync-loader-with-multiple-results.js
module.exports = function (content, map, meta) {
this.callback(null, someSyncOperation(content), map, meta);
return; // callback() í¨ì를 í¸ì¶íë©´ íì undefined를 ë°íí©ëë¤.
};ë¹ë기 ë¡ëì ê²½ì° ë¹ë기 í¨ììì ë³íë ì½í
ì¸ ë¥¼ ë°íí ì ììµëë¤.
async-loader.js
module.exports = async function (content, map, meta) {
var result = await someAsyncOperation(content);
return result;
};ëë this.async를 ì¬ì©íì¬ callback í¨ì를 ê²ìí ì ììµëë¤.
async-loader-with-callback.js
module.exports = function (content, map, meta) {
var callback = this.async();
someAsyncOperation(content, function (err, result) {
if (err) return callback(err);
callback(null, result, map, meta);
});
};async-loader-with-multiple-results.js
module.exports = function (content, map, meta) {
var callback = this.async();
someAsyncOperation(content, function (err, result, sourceMaps, meta) {
if (err) return callback(err);
callback(null, result, sourceMaps, meta);
});
};기본ì ì¼ë¡ 리ìì¤ íì¼ì UTF-8 문ìì´ë¡ ë³íëì´ ë¡ëì ì ë¬ë©ëë¤. raw íë그를 trueë¡ ì¤ì íë©´ ë¡ëê° ìì Buffer를 ë°ê² ë©ëë¤. 모ë ë¡ëë 결과를 String í¹ì Bufferë¡ ì ë¬í ì ììµëë¤. ì»´íì¼ë¬ë ë¡ë ì¬ì´ìì ë³íëì´ ìëë©ëë¤.
raw-loader.js
module.exports = function (content) {
assert(content instanceof Buffer);
return someSyncOperation(content);
// ë°í ê°ë `Buffer`ê° ë ì ììµëë¤.
// ë¡ëê° "raw"ê° ìë ê²½ì°ìë íì©ë©ëë¤.
};
module.exports.raw = true;ë¡ëë íì ì¤ë¥¸ìª½ìì ì¼ìª½ì¼ë¡ í¸ì¶ë©ëë¤. ë¡ëê° ìì² ë¤ì ë©í ë°ì´í°ìë§ ê´ì¬ì ëê³ ì´ì ë¡ëì 결과를 무ìí ì ìë ê²½ì°ê° ììµëë¤. ë¡ëì pitch ë©ìëë ë¡ëê° ì¤ì ë¡ ì¤í(ì¤ë¥¸ìª½ìì ì¼ìª½ì¼ë¡)ë기 ì ì ì¼ìª½ìì ì¤ë¥¸ìª½ì¼ë¡ í¸ì¶ë©ëë¤.
ë¤ìê³¼ ê°ì use ì¤ì ì ì´í´ë³´ê² ìµëë¤.
module.exports = {
//...
module: {
rules: [
{
//...
use: ['a-loader', 'b-loader', 'c-loader'],
},
],
},
};ë¤ì ë¨ê³ë¤ì´ ë°ìí©ëë¤.
|- a-loader `pitch`
|- b-loader `pitch`
|- c-loader `pitch`
|- ìì²ë 모ëì´ ìì¡´ì±ì¼ë¡ ì íë©ëë¤
|- c-loader ì ì ì¤í
|- b-loader ì ì ì¤í
|- a-loader ì ì ì¤íê·¸ë ë¤ë©´ ë¡ëê° "pitching" ë¨ê³ë¥¼ ì´ì©íë ì´ì ë 무ìì¼ê¹ì?
첫째, pitch ë©ìëì ì ë¬ë dataë ì¤í ë¨ê³ììë this.data ìëì ë
¸ì¶ëë©° ì¤í 주기ì ì´ê¸°ë¶í° ì 보를 캡ì²íê³ ê³µì íë ë° ì ì©í ì ììµëë¤.
module.exports = function (content) {
return someSyncOperation(content, this.data.value);
};
module.exports.pitch = function (remainingRequest, precedingRequest, data) {
data.value = 42;
};ë째, ë¡ëê° pitch ë°©ìì¼ë¡ 결과를 ì ë¬íë©´ íë¡ì¸ì¤ê° ëìê° ëë¨¸ì§ ë¡ë를 ê±´ëëëë¤. ìëë ìì ìììì b-loaderì pitch ë©ìëê° ë¬´ì¸ê°ë¥¼ ë°ííì ëì ê²½ì°ë¥¼ ì´í´ë´
ëë¤.
module.exports = function (content) {
return someSyncOperation(content);
};
module.exports.pitch = function (remainingRequest, precedingRequest, data) {
if (someCondition()) {
return (
'module.exports = require(' +
JSON.stringify('-!' + remainingRequest) +
');'
);
}
};ìì ë¨ê³ë ë¤ìê³¼ ê°ì´ ë¨ì¶ë©ëë¤.
|- a-loader `pitch`
|- b-loaderë `pitch`를 íµí´ 모ëì 리í´í©ëë¤
|- a-loader ì ì ì¤íë¡ë 컨í
ì¤í¸ë this ìì±ì í ë¹ë ë¡ë ë´ë¶ìì ì¬ì©í ì ìë ìì±ì ëíë
ëë¤.
ë¤ì ìì ê° ì£¼ì´ì§ë©´ require í¸ì¶ì´ ì¬ì©ë©ëë¤.
/abc/file.jsì ê²½ì°
require('./loader1?xyz!loader2!./resource?rrr');addContextDependency(directory: string)ë¡ë ê²°ê³¼ì ìì¡´ì±ì¼ë¡ ëë í°ë¦¬ë¥¼ ì¶ê°í©ëë¤.
addDependency(file: string)
dependency(file: string) // ë¨ì¶ê¸°ì¡´ íì¼ì ê°ìí ì ìê² ë§ë¤ê¸° ìí´ ë¡ë ê²°ê³¼ì ìì¡´ì±ì¼ë¡ íì¼ì ì¶ê°í©ëë¤. ì를 ë¤ì´, sass-loader, less-loaderë ê°ì ¸ì¨ css íì¼ì´ ë³ê²½ë ëë§ë¤ ì´ë¥¼ ì¬ì©íì¬ ì¬ì»´íì¼í©ëë¤.
addMissingDependency(file: string)ì¡´ì¬íì§ ìë íì¼ì ê°ìí ì ìê² ë§ë¤ê¸° ìí´ ë¡ë ê²°ê³¼ì ìì¡´ì±ì¼ë¡ íì¼ì ì¶ê°í©ëë¤. addDependencyì ì ì¬íì§ë§ ê°ììê° ì¬ë°ë¥´ê² ì°ê²°ë기 ì ì ì»´íì¼íë ëì íì¼ ìì±ì ì²ë¦¬í©ëë¤.
ë¡ëê° ë¹ëê¸°ë¡ ì½ë°±í ìì ìì loader-runnerì ì립ëë¤. this.callbackì ë°íí©ëë¤.
ìëë ìºì ê°ë¥ ì¬ë¶ë¥¼ íëê·¸ë¡ ì¤ì íë í¨ìì ëë¤.
cacheable(flag = true: boolean)기본ì ì¼ë¡ ë¡ë ê²°ê³¼ë ìºì ê°ë¥í ê²ì¼ë¡ íëê·¸ê° ì§ì ë©ëë¤. ë¡ëì 결과를 ìºìí ì ìëë¡ íë ¤ë©´ false를 ì ë¬í´ ì´ ë©ìë를 í¸ì¶íì¸ì.
ìºì ê°ë¥í ë¡ëë ì
ë ¥ê³¼ ìì¡´ì±ì´ ë³ê²½ëì§ ìë í ë³íì§ ìë 결과를 ê°ì ¸ì¼ í©ëë¤. ì´ë ë¡ëê° this.addDependencyë¡ ì§ì ë ê² ì´ì¸ì ìì¡´ì±ì ê°ì§ ììì¼ í¨ì ì미í©ëë¤.
ì¬ë¬ 결과를 ë°íí기 ìí´ ë기ì ëë ë¹ë기ìì¼ë¡ í¸ì¶í ì ìë í¨ìì ëë¤. ììëë ì¸ìë ë¤ìê³¼ ê°ìµëë¤.
this.callback(
err: Error | null,
content: string | Buffer,
sourceMap?: SourceMap,
meta?: any
);Error ëë nullì´ì´ì¼ í©ëë¤.string ëë Bufferì
ëë¤.ì´ í¨ìê° í¸ì¶ëë ê²½ì° ë¡ëì 모í¸í 결과를 í¼íê³ ì undefined를 ë°íí´ì¼ í©ëë¤.
clearDependencies();ë¡ë ê²°ê³¼ì 모ë ìì¡´ì±ì ì ê±°í©ëë¤. ì´ë ì´ê¸° ìì¡´ì±ê³¼ ë¤ë¥¸ ë¡ëì ìì¡´ì±ì í¬í¨í©ëë¤. pitch ì¬ì©ì ê³ ë ¤íì¸ì.
모ëì ëë í°ë¦¬. ë¤ë¥¸ ê²ì í´ìí기 ìí 컨í ì¤í¸ë¡ ì¬ì©í ì ììµëë¤.
ì´ ìì ìì resource.jsê° ì´ ëë í°ë¦¬ì ì기 ë문ì /abcê° ë©ëë¤.
ë¡ëì pitchì ì ì ì¤í ë¨ê³ ê°ì ê³µì ëë ë°ì´í° ê°ì²´ì ëë¤.
emitError(error: Error)ì¶ë ¥ìë íìë ì ìë ì¤ë¥ë¥¼ ë´ë³´ë ëë¤.
ERROR in ./src/lib.js (./src/loader.js!./src/lib.js)
Module Error (from ./src/loader.js):
Here is an Error!
@ ./src/index.js 1:0-25emitFile(name: string, content: Buffer|string, sourceMap: {...})íì¼ì ë´ë³´ë ëë¤. ì´ë webpackì ë°ë¼ ë¤ë¦ ëë¤.
emitWarning(warning: Error)ë¤ìê³¼ ê°ì´ ì¶ë ¥ì íìë ê²½ê³ ë¥¼ ë´ë³´ë ëë¤.
WARNING in ./src/lib.js (./src/loader.js!./src/lib.js)
Module Warning (from ./src/loader.js):
Here is a Warning!
@ ./src/index.js 1:0-25ìì±ë ë°íì ì½ëìì ì´ë¤ ì¢ ë¥ì ES 기ë¥ì ì¬ì©í ì ìëì§ íì¸íì¸ì.
ìì:
{
// íì´í í¨ì('() => { ... }')를 ì§ìí©ëë¤.
"arrowFunction": true,
// BigInt를 문ì ê·¸ëë¡ ì§ìí©ëë¤(ì를 ë¤ì´, 123n).
"bigIntLiteral": false,
// const ë° let ë³ì ì ì¸ì ì§ìí©ëë¤.
"const": true,
// destructuringì ì§ìí©ëë¤('{ a, b } = obj' ì²ë¼ ì¬ì©í©ëë¤).
"destructuring": true,
// EcmaScript 모ëì ê°ì ¸ì¤ë ë¹ë기 import() í¨ì를 ì§ìí©ëë¤.
"dynamicImport": false,
// íì¬ ì¹ ëìì ëí´ìë§ ìì
ì를 ë§ë¤ ë async import()를 ì§ìí©ëë¤.
"dynamicImportInWorker": false,
// 'for of' ë°ë³µì를 ì§ìí©ëë¤('for (const x of array) { ... }' ì²ë¼ ì¬ì©í©ëë¤).
"forOf": true,
// 'globalThis'를 ì§ìí©ëë¤.
"globalThis": true,
// ECMAScript 모ëì ê°ì ¸ì¤ë ECMAScript Module syntax를 ì§ìí©ëë¤(import ... from '...' ì²ë¼ ì¬ì©í©ëë¤).
"module": false,
// ìµì
ë ì²´ì´ë('obj?.a' ëë 'obj?.()')ì ì§ìí©ëë¤.
"optionalChaining": true,
// í
í릿 리í°ë´ì ì§ìí©ëë¤.
"templateLiteral": true
}compilationì inputFileSystem ìì±ì ì ê·¼í©ëë¤.
주ì´ì§ ë¡ë ìµì ì ì¶ì¶í©ëë¤. ì íì ì¼ë¡ JSON ì¤í¤ë§ë¥¼ ì¸ìë¡ íì©í©ëë¤.
getResolve(options: ResolveOptions): resolve
resolve(context: string, request: string, callback: function(err, result: string))
resolve(context: string, request: string): Promise<string>this.resolveì ì ì¬í resolve í¨ì를 ë§ëëë¤.
Webpack resolve ìµì
ìëì 모ë ìµì
ì´ ê°ë¥í©ëë¤. ì¤ì ë resolve ìµì
ê³¼ ë³í©ë©ëë¤. "..."ë resolve ìµì
ìì ê°ì íì¥í기 ìí´ ë°°ì´ìì ì¬ì©í ì ììµëë¤(ì: { extensions: [".sass", "..."] }).
options.dependencyTypeì ì¶ê° ìµì
ì
ëë¤. ì´ë ì°ë¦¬ê° resolve ìµì
ìì byDependency를 í´ìíë ë° ì¬ì©ëë ìì¡´ì± íì
ì ì§ì í ì ìëë¡ í©ëë¤.
í´ì ìì ì 모ë ìì¡´ì±ì íì¬ ëª¨ëì ëí ìì¡´ì±ì¼ë¡ ìë ì¶ê°ë©ëë¤.
ë¡ëì© HMRì ëí ì ë³´ì ëë¤.
module.exports = function (source) {
console.log(this.hot); // --hot íëê·¸ ëë webpack ì¤ì ì íµí´ HMRì´ íì±íë ê²½ì° trueì
ëë¤.
return source;
};string
í´ì를 ìì±í ë ì¬ì©í ì¸ì½ë©ì ëë¤. output.hashDigest를 ì°¸ê³ íì¸ì.
number
ì¬ì©í í´ì ë¤ì´ì ì¤í¸ì ì ëì¬ ê¸¸ì´ì ëë¤. output.hashDigestLength를 ì°¸ê³ íì¸ì.
string function
ì¬ì©í í´ì± ìê³ ë¦¬ì¦ì ëë¤. output.hashFunctionì ì°¸ê³ íì¸ì.
string
Node.JSì hash.update를 íµí´ í´ì를 ì
ë°ì´í¸íë ì íì saltì
ëë¤. output.hashSalt를 ì°¸ê³ íì¸ì.
this.importModule(request, options, [callback]): Promise
ìì ì»´íì¼ë¬ê° ë¹ë ì ìì²ì ì»´íì¼íê³ ì¤íí기 ìí ëì²´ ê²½ë ì루ì ì ëë¤.
request: 모ëì ë¡ëí ìì² ë¬¸ìì´ì
ëë¤options:
layer: ì´ ëª¨ëì´ ë°°ì¹/ì»´íì¼ëë ë ì´ì´ë¥¼ ì§ì í©ëë¤publicPath: ë¹ëë 모ëì ì¬ì©ëë ê³µê° ê²½ë¡ì
ëë¤callback: 모ëì export ëë ESMì© ë¤ìì¤íì´ì¤ ê°ì²´ë¥¼ 리í´íë Node.js ì¤íì¼ì ì íì ì½ë°± í¨ìì
ëë¤. ì½ë°±ì ì ê³µíì§ ìì¼ë©´ importModuleì´ Promise를 리í´í©ëë¤.webpack.config.js
module.exports = {
module: {
rules: [
{
test: /stylesheet\.js$/i,
use: ['./a-pitching-loader.js'],
type: 'asset/source', // ë¡ëê° ë¬¸ìì´ì 리í´íë¯ë¡ íì
ì 'asset/source'ë¡ ì¤ì í©ëë¤
},
],
},
};a-pitching-loader.js
exports.pitch = async function (remaining) {
const result = await this.importModule(
this.resourcePath + '.webpack[javascript/auto]' + '!=!' + remaining
);
return result.default || result;
};src/stylesheet.js
import { green, red } from './colors.js';
export default `body { background: ${red}; color: ${green}; }`;src/colors.js
export const red = '#f00';
export const green = '#0f0';src/index.js
import stylesheet from './stylesheet.js';
// ì¤íì¼ ìí¸ë ë¹ëì 문ìì´ `body { background: #f00; color: #0f0; }`ê° ë©ëë¤ì ììì ë¤ìê³¼ ê°ì ì¬ì¤ì ì ì ììµëë¤
!=! 구문ì ì¬ì©íì¬ ìì²ì ëí matchResource를 ì¤ì í©ëë¤. ì¦, ì본 리ìì¤ ëì module.rulesì ì¼ì¹ìí¤ê¸° ìí´ this.resourcePath + '.webpack[javascript/auto]'를 ì¬ì©í©ëë¤..webpack[javascript/auto]ë .webpack[type] í¨í´ì ì ì¬ íì¥ì´ë©°, ë¤ë¥¸ 모ë íì
ì´ ì§ì ëì§ ìì ê²½ì° ê¸°ë³¸ 모ë íì
ì ì§ì íë ë° ì¬ì©í©ëë¤. ì¼ë°ì ì¼ë¡ !=! 구문과 í¨ê» ì¬ì©ë©ëë¤.ìì ìë ë¨ìíë ìì ì´ë¯ë¡ webpack ì ì¥ììì ì ì²´ ìì 를 íì¸í ì ììµëë¤.
íì¬ ë¡ëì ë¡ë ë°°ì´ì ìë ì¸ë±ì¤ì ëë¤.
ìì ìì loader1ì 0, loader2ì 1ì
ëë¤.
loadModule(request: string, callback: function(err, source, sourceMap, module))모ëì ëí 주ì´ì§ ìì²ì í´ìíê³ ì¤ì ë 모ë ë¡ë를 ì ì©íê³ ìì±ë ìì¤, ìì¤ë§µ ë° ëª¨ë ì¸ì¤í´ì¤(ì¼ë°ì ì¼ë¡ NormalModuleì ì¸ì¤í´ì¤)ë¡ ì½ë°±í©ëë¤. 결과를 ìì±í기 ìí´ ë¤ë¥¸ 모ëì ìì¤ ì½ë를 ììì¼ íë ê²½ì° ì´ ê¸°ë¥ì ì¬ì©í©ëë¤.
ë¡ë 컨í
ì¤í¸ì this.loadModuleì 기본ì ì¼ë¡ CommonJS í´ì ê·ì¹ì ì¬ì©í©ëë¤. 'esm', 'commonjs' ëë ì¬ì©ì ì ìì ê°ì ë¤ë¥¸ í´ìì ì¬ì©í기 ì ì ì ì í dependencyTypeê³¼ í¨ê» this.getResolve를 ì¬ì©íì¸ì.
모ë ë¡ëì ë°°ì´ì ëë¤. pitch ë¨ê³ìì ì¸ ì ììµëë¤.
loaders = [{request: string, path: string, query: string, module: function}]ìì ì ë´ì©ì ëë¤.
[
{
request: '/abc/loader1.js?xyz',
path: '/abc/loader1.js',
query: '?xyz',
module: [Function],
},
{
request: '/abc/node_modules/loader2/index.js',
path: '/abc/node_modules/loader2/index.js',
query: '',
module: [Function],
},
];ì´ë¤ mode webpackì´ ì¤íëê³ ìëì§ ì½ìµëë¤.
ê°ë¥í ê°ì 'production', 'development', 'none'ì
ëë¤.
options ê°ì²´ë¡ ì¤ì ë ê²½ì° í´ë¹ ê°ì²´ë¥¼ ê°ë¦¬íµëë¤.optionsì´ ìì§ë§ 쿼리 문ìì´ë¡ í¸ì¶ë ê²½ì° ?ë¡ ììíë 문ìì´ì´ ë©ëë¤.í´ìë ìì² ë¬¸ìì´ì ëë¤.
ìì ì '/abc/loader1.js?xyz!/abc/node_modules/loader2/index.js!/abc/resource.js?rrr'
resolve(context: string, request: string, callback: function(err, result: string))require ííìê³¼ ê°ì ìì²ì resolve(í´ì)í©ëë¤.
contextë ëë í°ë¦¬ì ì ë ê²½ë¡ì¬ì¼ í©ëë¤. ì´ ëë í°ë¦¬ë í´ìì ìí ìì ìì¹ë¡ ì¬ì©ë©ëë¤.requestë í´ìë ìì²ì
ëë¤. ì¼ë°ì ì¼ë¡ ./relativeì ê°ì ìë ìì²ì´ë module/pathì ê°ì 모ëì´ ìì²ëì§ë§ /some/pathì ê°ì ì ë ê²½ë¡ë ìì²ì¼ë¡ ê°ë¥í©ëë¤.callbackì resolveë ê²½ë¡ë¥¼ ì ê³µíë ì¼ë° Node.js ì¤íì¼ ì½ë°± í¨ìì
ëë¤.resolve ìì ì 모ë ìì¡´ì±ì íì¬ ëª¨ëì ëí ìì¡´ì±ì¼ë¡ ìë ì¶ê°ë©ëë¤.
쿼리를 í¬í¨í ìì²ì 리ìì¤ ë¶ë¶ì ëë¤.
ìì ì '/abc/resource.js?rrr'
리ìì¤ íì¼ì ëë¤.
ìì ì '/abc/resource.js'
리ìì¤ì 쿼리ì ëë¤.
ìì ì '?rrr'
Webpack 4ë¶í° 기존ì this.options.contextë this.rootContextë¡ ì ê³µë©ëë¤.
ìì¤ë§µì ìì±í´ì¼ íëì§ ì¬ë¶ë¥¼ ìë ¤ì¤ëë¤. ìì¤ë§µì ìì±íë ê²ì ë¹ì©ì´ ë§ì´ ëë ìì ì´ë¯ë¡ ìì¤ë§µì´ ì¤ì ë¡ ìì²ëìëì§ íì¸í´ì¼ í©ëë¤.
ì»´íì¼ ëìì ëë¤. ì¤ì ìµì ìì ì ë¬ë©ëë¤.
ì: 'web', 'node'
ë¤ì ì í¸ë¦¬í°ì ì ê·¼í©ëë¤.
absolutify: ê°ë¥í ê²½ì° ì ë ê²½ë¡ë¥¼ ì¬ì©íì¬ ì ìì² ë¬¸ìì´ì 리í´í©ëë¤.contextify: ê°ë¥í ê²½ì° ì ë ê²½ë¡ë¥¼ í¼íë ì ìì² ë¬¸ìì´ì 리í´í©ëë¤.createHash: ì ê³µë í´ì í¨ììì ì Hash ê°ì²´ë¥¼ ë°íí©ëë¤.my-sync-loader.js
module.exports = function (content) {
this.utils.contextify(
this.context,
this.utils.absolutify(this.context, './index.js')
);
this.utils.absolutify(this.context, this.resourcePath);
const mainHash = this.utils.createHash(
this._compilation.outputOptions.hashFunction
);
mainHash.update(content);
mainHash.digest('hex');
// â¦
return content;
};ë¡ë API ë²ì ì
ëë¤. íì¬ë 2ë²ì ì
ëë¤. ì´ë ì´ì ë²ì ê³¼ì í¸íì±ì ì ê³µíë ë° ì ì©í©ëë¤. ë²ì ì ì¬ì©íì¬ ì»¤ì¤í
ëì ëë 주ì ë³ê²½ ì¬íì ëí ë체를 ì§ì í ì ììµëë¤.
ì´ booleanì webpackì ìí´ ì»´íì¼ë ë trueë¡ ì¤ì ë©ëë¤.
ë¡ë ì¸í°íì´ì¤ë 모ë 모ë ê´ë ¨ ì 보를 ì ê³µí©ëë¤. ê·¸ë¬ë ë문 ê²½ì°ë¡ ì»´íì¼ë¬ API ìì²´ì ì ê·¼í´ì¼ í ìë ììµëë¤.
ê·¸ë¬ë¯ë¡ ìµíì ìë¨ì¼ë¡ë§ ì¬ì©í´ì¼ í©ëë¤. ì´ ìì±ë¤ì ì¬ì©íë©´ ë¡ëì ë²ì©ì±ì´ ë¨ì´ì§ëë¤.
Webpackì íì¬ Compilation ê°ì²´ì ì ê·¼í©ëë¤.
Webpackì íì¬ Compiler ê°ì²´ì ì ê·¼í©ëë¤.
Boolean íëê·¸ì ëë¤. ëë²ê·¸ 모ëì¼ ë ì¤ì ë©ëë¤.
ë§ì§ë§ ë¡ëìì ì ë¬ëììµëë¤. ì ë ¥ ì¸ì를 모ëë¡ ì¤ííë ¤ë ê²½ì° ì´ ë³ì를 ë°ë¡ê°ê¸°(ì±ë¥ì©)ë¡ ì½ë ê²ì ê³ ë ¤íì¸ì.
ê²°ê³¼ê° ìµìí ëì´ì¼ íëì§ ì¬ë¶ë¥¼ ìë ¤ì¤ëë¤.
ë¤ì ë¡ëì ê°ì ì ë¬í©ëë¤. 모ëë¡ ì¤ííì ë ê²°ê³¼ê° ë¬´ìì ë´ë³´ë´ëì§ ìê³ ìë¤ë©´ ì¬ê¸°ìì ì´ ê°ì ì¤ì (ì ì¼í ë°°ì´ ììë¡)íììì¤.
ë¡ëëë 모ë ê°ì²´ì ëí hacky ì ê·¼.
ë¤ìì íµí´ ë¡ë ë´ë¶ìì ì¤ë¥ë¥¼ ë³´ê³ í ì ììµëë¤.
throw(í¹ì 기í ì¡íì§ ìë ìì¸)를 ì¬ì©í©ëë¤. ë¡ëê° ì¤íëë ëì ì¤ë¥ê° ë°ìíë©´ íì¬ ëª¨ë ì»´íì¼ì´ ì¤í¨í©ëë¤.callback(ë¹ë기 모ëìì)를 ì¬ì©í©ëë¤. ì½ë°±ì ì¤ë¥ë¥¼ ì ë¬íë©´ 모ë ì»´íì¼ ì¤í¨ë ë°ìí©ëë¤.ìì:
./src/index.js
require('./loader!./lib');ë¡ëìì ì¤ë¥ê° ë°ìíë ê²½ì°ì ëë¤.
./src/loader.js
module.exports = function (source) {
throw new Error('This is a Fatal Error!');
};ëë ë¹ë기 모ëìì ì½ë°±ì ì¤ë¥ë¥¼ ì ë¬íë ê²½ì°ì ëë¤.
./src/loader.js
module.exports = function (source) {
const callback = this.async();
//...
callback(new Error('This is a Fatal Error!'), source);
};모ëì ë¤ìê³¼ ê°ì´ ë²ë¤ë¡ ì ê³µë©ëë¤.
/***/ "./src/loader.js!./src/lib.js":
/*!************************************!*\
!*** ./src/loader.js!./src/lib.js ***!
\************************************/
/*! no static exports found */
/***/ (function(module, exports) {
throw new Error("Module build failed (from ./src/loader.js):\nError: This is a Fatal Error!\n at Object.module.exports (/workspace/src/loader.js:3:9)");
/***/ })
ê·¸í ë¤ì ë¹ë ì¶ë ¥ìë ì¤ë¥ê° íìë©ëë¤(this.emitErrorì ì ì¬í©ëë¤).
ERROR in ./src/lib.js (./src/loader.js!./src/lib.js)
Module build failed (from ./src/loader.js):
Error: This is a Fatal Error!
at Object.module.exports (/workspace/src/loader.js:2:9)
@ ./src/index.js 1:0-25ìëìì ë³¼ ì ìë¯ì´ ì¤ë¥ ë©ìì§ë¿ë§ ìëë¼ ê´ë ¨ ë¡ë ë° ëª¨ëì ëí ì¸ë¶ ì ë³´ë íìë©ëë¤.
ERROR in ./src/lib.js(./src/loader.js!./src/lib.js)(from ./src/loader.js)@ ./src/index.js 1:0-25ìë¡ì´ ì¸ë¼ì¸ ìì² êµ¬ë¬¸ì´ webpack v4ì ëì
ëììµëë¤. ìì²ì ì ëì¬ <match-resource>!=!를 ë¶ì´ë©´ ì´ ìì²ì ëí matchResourceê° ì¤ì ë©ëë¤.
matchResourceê° ì¤ì ëë©´ ìë 리ìì¤ ëì module.rulesì ì¼ì¹íë ë° ì¬ì©ë©ëë¤. ì´ë 리ìì¤ì ì¶ê° ë¡ë를 ì ì©í´ì¼ íê±°ë 모ë ì íì ë³ê²½í´ì¼ íë ê²½ì°ì ì ì©í ì ììµëë¤. ëí íµê³ì íìëë©° splitChunksìì testì Rule.issuer를 ì¼ì¹ìí¤ë ë° ì¬ì©ë©ëë¤.
ìì :
file.js
/* STYLE: body { background: red; } */
console.log('yep');ë¡ëë íì¼ì ë¤ì íì¼ë¡ ë³ííê³ matchResource를 ì¬ì©íì¬ ì¬ì©ì ì§ì CSS ì²ë¦¬ ê·ì¹ì ì ì©í ì ììµëë¤.
file.js (ë¡ëì ìí´ ë³íëììµëë¤)
import './file.js.css!=!extract-style-loader/getStyles!./file.js';
console.log('yep');ì´ë extract-style-loader/getStyles!./file.jsì ì¢
ìì±ì ì¶ê°íê³ ê²°ê³¼ë¥¼ file.js.cssë¡ ì²ë¦¬í©ëë¤. module.rulesìë /\.css$/ì ì¼ì¹íë ê·ì¹ì´ ìê³ ì´ ì¢
ìì±ì ì ì©ë기 ë문ì
ëë¤.
ë¡ëë ë¤ìê³¼ ê°ì´ ë³´ì¼ ì ììµëë¤.
extract-style-loader/index.js
const getStylesLoader = require.resolve('./getStyles');
module.exports = function (source) {
if (STYLES_REGEXP.test(source)) {
source = source.replace(STYLES_REGEXP, '');
return `import ${JSON.stringify(
this.utils.contextify(
this.context || this.rootContext,
`${this.resource}.css!=!${getStylesLoader}!${this.remainingRequest}`
)
)};${source}`;
}
return source;
};extract-style-loader/getStyles.js
module.exports = function (source) {
const match = source.match(STYLES_REGEXP);
return match[0];
};ë¡ê¹
APIë webpack 4.37 릴리ì¦ë¶í° ì¬ì©í ì ììµëë¤. stats ì¤ì ìì loggingì´ íì±íëê±°ë infrastructure ë¡ê¹
ì´ íì±íëë©´ ë¡ëê° ë©ì¸ì§ë¥¼ 기ë¡í ì ìì¼ë©° ì´ ë©ì¸ì§ë í´ë¹ ë¡ê±° íì(stats, infrastructure)ì¼ë¡ ì¶ë ¥ë©ëë¤.
this.getLogger()를 ì¬ì©íë ê²ì ì í¸í´ì¼ í©ëë¤. ì´ë ë¡ë ê²½ë¡ì ì²ë¦¬ë íì¼ì í¬í¨í compilation.getLogger()ì ë¨ì¶ì´ì
ëë¤. ì´ë¬í ì¢
ë¥ì ë¡ê¹
ì statsì ì ì¥ëê³ ê·¸ì ë°ë¼ íìì´ ì§ì ë©ëë¤. webpack ì¬ì©ìê° íí°ë§íê³ ë´ë³´ë¼ ì ììµëë¤.this.getLogger('name')를 ì¬ì©íì¬ ìì ì´ë¦ì ê°ì§ ë
립 ë¡ê±°ë¥¼ ì»ì ì ììµëë¤. ë¡ë ê²½ë¡ ë° ì²ë¦¬ë íì¼ì ê³ì ì¶ê°ë©ëë¤.getLogger ë°©ìì ì§ìíì§ ìë ì´ì webpack ë²ì ì´ ì¬ì©ëë ê²½ì° ëì²´ ì½ë를 ì ê³µí기 ìí´ this.getLogger ? this.getLogger() : console를 ê°ì§íë í¹ì í ëì²´ ì½ë를 ì¬ì©í ì ììµëë¤.