웹 팩 이 어떻게 작 동 하 는 지 자세히 분석 합 니 다.
웹 팩 설정 파일 은 주로 입구(entry),출력 파일(output),모드,로 더(Loader),플러그 인(Plugin)등 몇 부분 을 포함 하고 있 음 을 알 고 있 습 니 다.단,JS 파일 만 구성 하면 입구 와 출력 파일 경 로 를 지정 하면 미니 프로젝트 의 포장 을 완성 할 수 있 습 니 다.웹 팩 이 어떻게 작 동 하 는 지 간단 한 프로젝트 를 통 해 알 아 보 겠 습 니 다.
동기 화 로드
본 고 는 웹 팩^4.3.0 을 예시 로 사용 합 니 다.생산 된 파일 을 더욱 잘 관찰 하기 위해 서,우 리 는 모델 을 development 폐쇄 코드 압축 으로 설정 하고,source-map 를 열 어 원본 코드 디 버 깅 을 지원 합 니 다.그 외 에원본 코드 의 설명 을 제거 하기 위해 플러그 인 MyPlugin 을 간단하게 썼 습 니 다.
새 src/index.js:
console.log('Hello webpack!');
새 웹 팩 설정 파일 웹 팩.config.js
const path = require('path');
const MyPlugin = require('./src/MyPlugin.js')
module.exports = {
mode: 'development',
devtool: 'source-map',
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist')
},
plugins:[
new MyPlugin()
]
};
src/MyPlugin.js 를 새로 만 듭 니 다.웹 팩 플러그 인 에 대한 더 많은 정보 알 아 보기
class MyPlugin {
constructor(options) {
this.options = options
this.externalModules = {}
}
apply(compiler) {
var reg = /("([^\\\"]*(\\.)?)*")|('([^\\\']*(\\.)?)*')|(\/{2,}.*?(\r|
))|(\/\*(
|.)*?\*\/)|(\/\*\*\*\*\*\*\/)/g
compiler.hooks.emit.tap('CodeBeautify', (compilation)=> {
Object.keys(compilation.assets).forEach((data)=> {
let content = compilation.assets[data].source() //
content = content.replace(reg, function (word) { //
return /^\/{2,}/.test(word) || /^\/\*!/.test(word) || /^\/\*{3,}\//.test(word) ? "" : word;
});
compilation.assets[data] = {
source(){
return content
},
size(){
return content.length
}
}
})
})
}
}
module.exports = MyPlugin
현재 웹 팩--config webpack.config.js 명령 을 실행 하고 있 습 니 다.포장 이 완료 되면 출력 디 렉 터 리 dist:dist/main.js 가 더 나 옵 니 다.main 은 웹 팩 의 기본 설정 인 출력 파일 이름 입 니 다.이 파일 을 빠르게 살 펴 보 겠 습 니 다.
(function(modules){
// ...
})({
"./src/index.js": (function(){
// ...
})
});
전체 파일 은 즉시 실행 함수(IIFE)만 포함 되 어 있 습 니 다.웹 팩 Bootstrap 이 라 고 부 릅 니 다.대상 만 받 습 니 다.불 러 오지 않 은 모듈 집합(modules)입 니 다.이 modules 대상 의 key 는 하나의 경로 이 고 value 는 함수 입 니 다.너 는 아마도 이곳 의 모듈 이 무엇 이 냐 고 물 을 것 이다.그것들 은 또 어떻게 불 러 옵 니까?생산 코드 를 자세히 보기 전에 우 리 는 먼저 소스 코드 를 풍부하게 합 니 다.
새 파일 src/utils/math.js:
export const plus = (a, b) => {
return a + b;
};
src/index.js 수정:
import { plus } from './utils/math.js';
console.log('Hello webpack!');
console.log('1 + 2: ', plus(1, 2));
우 리 는 ES 규범 의 모듈 화 문법 에 따라 간단 한 모듈 src/utils/math.js 를 써 서 src/index.js 에 인용 했다.웹 팩 은 자신의 방식 으로 ES6 Module 규범 을 지 원 했 는데 앞에서 언급 한 module 은 바로 ES6 module 에 대응 하 는 개념 이다.다음은 이 모듈 들 이 어떻게 ES5 코드 를 통 해 이 루어 졌 는 지 살 펴 보 자.명령 webpack--config webpack.config.js 를 다시 실행 한 후 출력 파일 보기:
(function(modules){
// ...
})({
"./src/index.js": (function(){
// ...
}),
"./src/utils/math.js": (function() {
// ...
})
});
IIFE 가 들 어 오 는 modules 대상 에 키 값 이 하나 더 있 습 니 다.새 모듈 src/utils/math.js 에 대응 합 니 다.이것 은 우리 가 소스 코드 에서 분 리 된 모듈 과 서로 호응 합 니 다.그러나 modules 가 있 는 것 은 첫 번 째 단계 입 니 다.이 파일 이 최종 적 으로 이 루어 진 효 과 는 각 모듈 을 개발 자 들 이 편성 한 순서대로 실행 하 는 것 입 니 다.웹 팩 Bootstrap 탐구
다음은 웹 팩 Bootstrap 함수 중 어떤 것들 이 있 는 지 살 펴 보 겠 습 니 다.
// webpackBootstrap
(function(modules){
// __webpack_require__
var installedModules = {};
/**
* Webpack , webpack
* @param {String} moduleId ID, , "./src/index.js"
* @returns {Object} exports
*/
function __webpack_require__(moduleId) {
// ...
}
// __webpack_require__ ...
// "./src/index.js"
return __webpack_require__(__webpack_require__.s = "./src/index.js");
})(/* modules */);
주로 두 가지 일 을 한 것 을 볼 수 있다.모듈 로 딩 함수 정의webpack_require__。
로 딩 함 수 를 사용 하여 입구 모듈"./src/index.js"를 불 러 옵 니 다.
전체 웹 팩 Bootstrap 에 입구 모듈 의 그림자 만 나 타 났 습 니 다.다른 모듈 은 어떻게 불 러 옵 니까?우 리 는webpack_require__("./src/index.js")로 딩 함수 의 내부 논 리 를 자세히 봅 니 다.
function __webpack_require__(moduleId) {
//
if (installedModules[moduleId]) {
return installedModules[moduleId].exports;
}
// , ,
var module = installedModules[moduleId] = {
i: moduleId, // ID
l: false, //
exports: {} //
};
/**
*
* @param module.exports -- , this
* @param module --
* @param module.exports --
* @param __webpack_require__ --
*/
modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
//
module.l = true;
//
return module.exports;
}
우선,로드 함 수 는 패 킷 변수 인 installed Modules 를 사용 하여 불 러 온 모듈 을 메모리 에 저장 합 니 다.다음은 모듈 대상 을 초기 화하 고 캐 시 에 마 운 트 합 니 다.그 다음 에 모듈 의 실행 과정 입 니 다.입구 파일 을 불 러 올 때 modules[moduleId]는 사실은.../src/index.js 에 대응 하 는 모듈 함수 입 니 다.모듈 함 수 를 실행 하기 전에 모듈 과 관련 된 몇 개의 실제 인삼 이 들 어 와 모듈 이 내용 을 내 보 내 고 다른 모듈 의 내 보 낼 수 있 도록 합 니 다.마지막 으로 이 모듈 의 로드 가 완료 되 었 음 을 표시 하고 모듈 의 내 보 내기 내용 을 되 돌려 줍 니 다.근거webpack_require__ 의 캐 시 와 내 보 내기 논 리 는 전체 IIFE 가 실행 되 는 과정 에서 캐 시 된 모듈 을 불 러 올 때 installed Modules[moduleId].exports 로 돌아 간 다 는 것 을 알 고 있 습 니 다.다시 말 하면 같은 모듈 은 처음 인 용 될 때 만 모듈 자 체 를 실행 할 수 있 습 니 다.
모듈 실행 함수
__webpack_require__모듈 실행 함 수 를 modules[moduleId].call()을 통 해 실 행 했 습 니 다.다음은 웹 packBootstrap 의 매개 변수 부분 에 들 어가 모듈 의 실행 함 수 를 보 겠 습 니 다.
/*** ./src/index.js ***/
"./src/index.js": (function (module, __webpack_exports__, __webpack_require__) {
"use strict";
// ES , demo, 。
__webpack_require__.r(__webpack_exports__);
/* harmony import */
// ,`import {plus} from './utils/math.js';` loader 。
// "./src/utils/math.js" ,
var _utils_math_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/utils/math.js");
console.log('Hello webpack!');
console.log('1 + 2: ', Object(_utils_math_js__WEBPACK_IMPORTED_MODULE_0__["plus"])(1, 2));
}),
"./src/utils/math.js": (function (module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */
// ,`export` loader 。
__webpack_require__.d(__webpack_exports__, "plus", function () {
return plus;
});
const plus = (a, b) => {
return a + b;
};
})
실행 순 서 는 입구 모듈->도구 모듈->입구 모듈 입 니 다.입구 모듈 중 우선webpack_require__("./src/utils/math.js")도구 모듈 의 exports 대상 을 받 았 습 니 다.도구 모듈 을 다시 보면 ES 내 보 내기 문법 이 로 바 뀌 었 습 니 다.webpack_require__.d(__webpack_exports__, [key],[getter]),그리고webpack_require__.d 함수 의 정 의 는 웹 packBootstrap 에 있 습 니 다:
// exports 。
__webpack_require__.d = function (exports, name, getter) {
// exports ( ) [name] , getter。
if (!__webpack_require__.o(exports, name)) {
Object.defineProperty(exports, name, {
enumerable: true,
get: getter
});
}
};
// Object.prototype.hasOwnProperty 。
__webpack_require__.o = function (object, property) {
return Object.prototype.hasOwnProperty.call(object, property);
};
가시webpack_require__.d.사실은 Object.defineProperty 의 간단 한 포장 입 니 다.도구 모듈 에서 내 보 낸 변 수 를 참조 한 후 입구 모듈 에서 나머지 부분 을 실행 합 니 다.이로써 웹 팩 의 기본 모듈 실행 과정 은 끝났다.
자,우 리 는 프로 세 스 맵 으로 웹 팩 모듈 의 로드 방향 을 정리 합 니 다.
비동기 로드
위의 포장 이 있 습 니 다.우 리 는 서로 다른 포장 을 main.js 파일 에 넣 는 것 을 발 견 했 습 니 다.main.js 는 네트워크 자원 을 너무 많이 소모 하여 사용자 가 웹 페이지 와 상호작용 을 시작 하 는 데 오래 기 다 려 야 합 니 다.
일반적인 해결 방식 은 수요 에 따라 첫 번 째 로 딩 파일 의 부 피 를 낮 추고 필요 할 때(예 를 들 어 전단 공유 기 전환,인 터 랙 션 이벤트 리 셋)다른 파일 을 비동기 로 불 러 오고 그 중의 모듈 을 사용 하 는 것 이다.
웹 팩 은 ES import()규범 으로 비동기 로 모듈 을 불 러 오 는 것 을 추천 합 니 다.ES 규범 에 따라 입구 모듈 의 import 방식 을 수정 하여 비동기 로 모듈 을 불 러 올 수 있 도록 합 니 다.
src/index.js
console.log('Hello webpack!');
window.setTimeout(() => {
import('./utils/math').then(mathUtil => {
console.log('1 + 2: ' + mathUtil.plus(1, 2));
});
}, 2000);
도구 모듈(src/utils/math.js)은 여전히 변 하지 않 습 니 다.웹 팩 설정 에서 자원 파일 의 공공 자원 경로(PublicPath)를 지정 하면 뒤의 탐색 과정 에서 만 날 수 있 습 니 다.
const path = require('path');
const MyPlugin = require('./src/MyPlugin.js')
module.exports = {
mode: 'development',
devtool: 'source-map',
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
publicPath: '/dist/'
},
plugins:[
new MyPlugin()
]
};
이어서 포장 을 실행 하면 dist/main.js 를 제외 하고 dist/0.js./src/utils/math.js 가 하나 더 생 겼 습 니 다.모듈 이 main chunk 에서 0 chunk 로 옮 겨 졌 습 니 다.demo 1 과 달리 main chunk 에 비동기 로드 에 사용 할 코드 가 추가 되 었 습 니 다.개관 해 보 겠 습 니 다.
// webpackBootstrap
(function (modules) {
// chunk
function webpackJsonpCallback(data) {
// ...
}
// ...
// chunk ,0
var installedChunks = {
"main": 0
};
// chunk
function jsonpScriptSrc(chunkId) {
// ...
}
// require ,
function __webpack_require__(moduleId) {
// ...
}
// chunk, promise
__webpack_require__.e = function requireEnsure(chunkId) {
// ...
}
// ...
// defineProperty ,
__webpack_require__.d = function (exports, name, getter) {}
// ...
// publicPath
__webpack_require__.p = "/dist/";
/**** JSONP ****/
var jsonpArray = window["webpackJsonp"] = window["webpackJsonp"] || [];
var oldJsonpFunction = jsonpArray.push.bind(jsonpArray);
jsonpArray.push = webpackJsonpCallback;
jsonpArray = jsonpArray.slice();
for (var i = 0; i < jsonpArray.length; i++) webpackJsonpCallback(jsonpArray[i]);
var parentJsonpFunction = oldJsonpFunction;
/**** JSONP ****/
return __webpack_require__(__webpack_require__.s = "./src/index.js");
})({
"./src/index.js": (function(module, exports, __webpack_require__) {
document.write('Hello webpack!
');
window.setTimeout(() => {
__webpack_require__.e(/*! import() */ 0).then(__webpack_require__.bind(null, /*! ./utils/math */ "./src/utils/math.js")).then(mathUtil => {
console.log('1 + 2: ' + mathUtil.plus(1, 2));
});
}, 2000);
})
})
웹 팩 Bootstrap 의 함수 체 부분 에 내용 이 추 가 된 것 을 볼 수 있 습 니 다.매개 변수 부분 은"./src/utils/math.js"모듈 을 제거 하 였 습 니 다.패키지 함수 의 실행 순 서 를 따라'JSONP 초기 화'부분 에 초점 을 맞 춥 니 다.
// jsonp , []
var jsonpArray = window["webpackJsonp"] = window["webpackJsonp"] || [];
// jsonpArray push , Array.prototype.push
var oldJsonpFunction = jsonpArray.push.bind(jsonpArray);
// jsonpArray push webpackJsonpCallback ( chunk )
jsonpArray.push = webpackJsonpCallback;
// jsonpArray ,push Array.prototype.push
jsonpArray = jsonpArray.slice();
// jsonpArray [],
for (var i = 0; i < jsonpArray.length; i++) webpackJsonpCallback(jsonpArray[i]);
// Array.prototype.push
var parentJsonpFunction = oldJsonpFunction;
초기 화가 끝 난 후,변 화 는 window 에 webpackJSonp 배열 을 마 운 트 한 것 입 니 다.값 은[]입 니 다.또한,이 배열 의 push 는 웹 팩 Jsonp Callback 함수 로 바 뀌 었 습 니 다.우 리 는 뒤에서 이러한 준비 작업 의 역할 을 언급 할 것 입 니 다.다음은webpack_require__입구 모듈,왜냐하면webpack_require__ 함수 가 변 하지 않 았 습 니 다.우 리 는 입구 모듈 의 실행 함수 에 어떤 변화 가 있 는 지 계속 관찰 합 니 다.
분명히 import('../utils/math.js')가 로 바 뀌 었 다.webpack_require__.e(0).then(__webpack_require__.bind(null, "./src/utils/math.js"))。0 은./src/utils/math.js 가 있 는 chunk 의 id 입 니 다.'동기 화 로드 모듈'의 논 리 는'chunk 를 먼저 불 러 오고 완성 한 후에 모듈 을 불 러 옵 니 다'로 나 누 었 습 니 다.
우 리 는webpack_require__.e 의 정의 위치:
__webpack_require__.e = function requireEnsure(chunkId) {
var promises = [];
// installedChunks webpackBootstrap chunk
var installedChunkData = installedChunks[chunkId];
// chunk
if(installedChunkData !== 0) {
// installedChunkData promise chunk
if(installedChunkData) {
promises.push(installedChunkData[2]);
} else {
/*** chunk: ***/
// promise
var promise = new Promise(function(resolve, reject) {
installedChunkData = installedChunks[chunkId] = [resolve, reject];
});
promises.push(installedChunkData[2] = promise);
// script chunk
var head = document.getElementsByTagName('head')[0];
var script = document.createElement('script');
var onScriptComplete;
// ... script
// src publicPath chunkId
script.src = jsonpScriptSrc(chunkId);
// , script 、 、
onScriptComplete = function (event) {
script.onerror = script.onload = null; // IE
clearTimeout(timeout);
var chunk = installedChunks[chunkId];
// script , chunk
if(chunk !== 0) {
// chunk
if(chunk) {
var errorType = event && (event.type === 'load' ? 'missing' : event.type);
var realSrc = event && event.target && event.target.src;
var error = new Error('Loading chunk ' + chunkId + ' failed.
(' + errorType + ': ' + realSrc + ')');
error.type = errorType;
error.request = realSrc;
// reject(error)
chunk[1](error);
}
// chunk
installedChunks[chunkId] = undefined;
}
};
// 12
var timeout = setTimeout(function(){
onScriptComplete({ type: 'timeout', target: script });
}, 120000);
script.onerror = script.onload = onScriptComplete;
head.appendChild(script);
/*** chunk ***/
}
}
return Promise.all(promises);
};
좀 길 어 보 입 니 다.우 리 는 한 걸음 한 걸음 분석 합 니 다.먼저 첫 줄 과 마지막 줄 을 보면 전체 함수 가 비동기 로 불 러 오 는 과정 을 promise 에 봉 하여 최종 적 으로 내 보 냅 니 다.이 어 두 번 째 줄 부터 installedChunkData 가 캐 시 에서 값 을 가 져 왔 습 니 다.chunk 를 처음 불 러 올 때 여 기 는 undefined 입 니 다.이 어 인 스 톨 드 ChunkData 의 undefined 값 은 1 층 if 문장의 판단 조건 을 촉발 시 켰 다.이 어 2 층 if 문 구 를 진행 합 니 다.이때 판단 조건 에 따라 else 블록 에 들 어 갑 니 다.여기 if 블록 에 있 는 내용 은 우리 가 먼저 전략 적 으로 건 너 뛰 었 습 니 다.else 에는 주로 두 개의 내용 이 있 습 니 다.하 나 는 chunk 스 크 립 트 로 딩 과정 입 니 다.이 과정 에서 script 라벨 을 만들어 chunk 가 있 는 주 소 를 요청 하고 chunk 내용 을 실행 하도록 합 니 다.둘째,promise 를 초기 화하 고 promis 로 chunk 파일 로드 과정 을 제어 합 니 다.
그러나,우 리 는 이 else 코드 블록 에서 reject 의 사용 처 를 찾 았 습 니 다.즉,chunk 에서 이상 을 불 러 올 때 chunk[1](error)를 찾 았 을 뿐,더 중요 한 resolve 의 사용 장 소 는 발견 되 지 않 았 습 니 다.단지 resolve 를 캐 시 에 걸 었 을 뿐 입 니 다(installedChunks[chunkId]=[resolve,reject]).
여기 chunk 파일 을 불 러 오 면 무슨 일이 일어 날 까요?dist/0.js 를 열 어 보 겠 습 니 다.
(window["webpackJsonp"] = window["webpackJsonp"] || []).push([[0], {
"./src/utils/math.js":
(function (module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */
__webpack_require__.d(__webpack_exports__, "plus", function () {
return plus;
});
const plus = (a, b) => {
return a + b;
};
})
}]);
우 리 는 발견 했다.오 랜 만 에./src/utils/math.js 모듈
window["webpackJSonp"]배열 의 사용 장소
이 코드 가 실행 되 기 시 작 했 습 니 다.비동기 로 연 결 된 chunk id 와 모듈 을 push 함수 에 전달 합 니 다.앞에서 언급 했 듯 이 window["webpackJSonp"]배열 의 push 함 수 는 webpackJSonpCallback 함수 로 재 작성 되 었 습 니 다.정의 위 치 는 webpackBootstrap 에 있 습 니 다.
function webpackJsonpCallback(data) {
var chunkIds = data[0];
var moreModules = data[1];
// then flag all "chunkIds" as loaded and fire callback
var moduleId, chunkId, i = 0, resolves = [];
// chunk
for(;i < chunkIds.length; i++) {
chunkId = chunkIds[i];
if(installedChunks[chunkId]) {
resolves.push(installedChunks[chunkId][0]);
}
installedChunks[chunkId] = 0;
}
// "moreModules" webpackBootstrap modules 。
for(moduleId in moreModules) {
if(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {
modules[moduleId] = moreModules[moduleId];
}
}
// parentJsonpFunction window["webpackJsonp"] push
// data , chunk
if(parentJsonpFunction) parentJsonpFunction(data);
// resolve , chunk promise resolved,then 。
while(resolves.length) {
resolves.shift()();
}
};
이 함수 에 들 어가 면 비동기 로 불 러 온 chunk 내용 을 가 져 왔 음 을 의미 합 니 다.이 럴 때 우 리 는 두 가지 일 을 완성 해 야 합 니 다.하 나 는 이번 비동기 로 불 러 온 결과 에 의존 하 는 모듈 을 계속 실행 하 게 하 는 것 입 니 다.다른 하 나 는 캐 시 로 딩 결과 입 니 다.첫 번 째 에 대해 서 는 그 전webpack_require__.e 의 내용,이때 chunk 는'불 러 오 는 중'상태 에 있 습 니 다.즉,대응 하 는 installedChunks[chunkId]의 값 은[resolve,reject,promise]입 니 다.여기 서 chunk 는 불 러 왔 지만 promise 는 아직 결정 되 지 않 았 습 니 다.그래서 webpackJSonpCallback 내부 에서 resolves 변 수 를 정의 하여 installedChunks 의 resolve 를 수집 하고 실행 합 니 다.
다음은 두 번 째 로 말하자면 몇 가지 차원 의 캐 시 와 관련 되 어야 한다.
우선 chunk 차원 입 니 다.여 기 는 두 가지 관련 조작 이 있 습 니 다.하 나 는 installedChunks[chunkId]를 0 으로 설정 하면webpack_require__.e.같은 chunk 를 두 번 째 로 불 러 올 때 즉시 결 의 된 promise(Promise.all([])를 되 돌려 줍 니 다.작업 2.chunk data 를 window["webpackJSonp"]배열 에 추가 하면 다 중 입구 모드 에서 불 러 온 chunk 캐 시 를 편리 하 게 가 져 올 수 있 습 니 다.다음 코드 를 통 해 구현:
/*** ***/
var jsonpArray = window["webpackJsonp"] = window["webpackJsonp"] || [];
// ...
for (var i = 0; i < jsonpArray.length; i++) webpackJsonpCallback(jsonpArray[i]);
var parentJsonpFunction = oldJsonpFunction;
/*** ***/
/*** ***/
function webpackJsonpCallback(data) {
//...
// parentJsonpFunction window["webpackJsonp"] push
if (parentJsonpFunction) parentJsonpFunction(data);
//...
}
/*** ***/
그리고 modules 차원 에서 chunk 의 moreModules 는 입구 파일 의 modules 에 합 쳐 져 다음 마이크로 작업 의 를 제공 할 수 있 습 니 다.webpack_require__ 동기 화 로드 모듈.
({
"./src/index.js":
(function (module, exports, __webpack_require__) {
console.log('Hello webpack!');
window.setTimeout(() => {
__webpack_require__.e(0).then(__webpack_require__.bind(null, "./src/utils/math.js")).then(mathUtil => {
console.log('1 + 2: ' + mathUtil.plus(1, 2));
});
}, 2000);
})
});
__webpack_require__.e(0)돌아 온 promise 결의 후,webpack_require__.bid(null,"./src/utils/math.js")는 chunk 가 가지 고 있 는 모듈 에 불 러 오고 다음 마이크로 태 스 크 함수 의 입 참 으로 모듈 을 되 돌려 줍 니 다.다음은 Webpack Loader 가 번역 한 다른 업무 코드 입 니 다.이제 비동기 절 차 를 정리 합 시다.
더 많은 웹 팩 의 기초 지식 은 아래 의 관련 글 을 클릭 하 세 요.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Webpack의 Loader와 Plugin의 차이점모듈 원본 코드의 변환에 사용됩니다.loader는 웹팩이 비javascript 모듈을 어떻게 처리하고 buld에 이러한 의존을 도입하는지 설명합니다.loader는 파일을 다른 언어(예: TypeScript)에서 Ja...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.