Webpack Plugin 개발
Plugin은 Webpack 엔진의 모든것을 개발자에게 공개합니다. 단계별 빌드 Callback을 사용하여 개발자는 Webpack 빌드 프로세스에 자신의 동작을 추가할 수 있습니다. Plugin 작성은 Loader를 빌드하는 것보다 조금더 진보된 것입니다. 왜냐하면 Webpack 하위 레벨 내부를 이해해야 할 필요가 있기 때문입니다.
Plugin 만들기
Webpack 용 Plugin은 다음과 같이 구성됩니다.
- 이름이 부여된 JavaScript 함수.
- 프로토 타입에
apply
메서드를 정의. - Webpack의 Event Hook을 특정하고 Attach.
- Webpack 내부 인스턴스 특정 데이터를 조작.
- 기능이 완료된 후 Webpack에서 Callback을 호출.
|
|
Plugin을 개발할 때 가장 중요한 두가지 자원 compiler
와 compilation
객체가 있습니다. 이 두 객체의 역할을 이해하는 것은 Webpack 엔진을 확장하는 중요한 첫단계입니다.
compiler
객체는 완전히 구성된 Webpack 환경을 나타냅니다. 이 객체는 Webpack이 시작할 때 한번 빌드되며 Option, Loader 및 Plugin을 포함한 모든 작업 설정으로 구성됩니다. Webpack 환경에 Plugin을 적용할 때 Plugin이compiler
에 대한 참조를 받습니다.compiler
를 사용하여 기본 Webpack 환경을 액세스할 수 있습니다.compilation
객체는 버전이 있는 Asset 하나의 빌드를 나타냅니다. Webpack 개발 미들웨어를 실행하는 동안 파일 변경이 감지될 때마다 새로운compilation
이 생성되어 새로운 컴파일된 Asset이 생성됩니다.compilation
은 모듈 리소스, 컴파일된 Asset, 변경된 파일 감시
및 종속성의 현재 상태에 대한 정보를 나타냅니다.compilation
은 또한 Plugin이 사용자 정의 작업을 수행하도록 선택할 수 있는 많은 Callback 포인트를 제공합니다.
두 구성 요소는 모든 Webpack Plugin (특히 compilation
)의 핵심 부분이므로 개발자는 다음 소스 파일을 알아두면 도움이됩니다.
Plugin 기본 구조
Plugin은 프로토타입에 apply
메서드가있는 인스턴스 객체입니다. 이 apply
메서드는 Plugin을 설치하는 동안 Webpack compiler
에 의해 한번 호출됩니다. apply
메서드는 compiler
Callback에 대한 액세스를 허용하는 기본 Webpack compiler
에 대한 참조를 제공받습니다. 간단한 Plugin은 다음과 같이 구성됩니다.
|
|
그런 다음 Plugin을 설치하려면 Webpack 설정파일의 plugins
배열에 인스턴스를 포함하면 됩니다.
|
|
compilation 접근하기
compiler
객체를 사용하면 각각의 새로운 compilation
에 대한 참조를 제공하는 Callback을 바인드할 수 있습니다. 이러한 compilation
은 빌드 프로세스 내에서 수많은 단계를 Hook하기 위한 콜백을 제공합니다.
|
|
compiler
,compilation
및 다른 중요한 객체에서 사용할 수있는 Callback에 대한 자세한 내용은 plugins을 참조하십시오.
비동기 compilation Plugin
일부 compilation
Plugin 단계는 비동기이며, Plugin 실행이 끝나면 호출되어야하는 Callback 함수를 전달합니다.
|
|
예제
일단 Webpack compiler
와 개별 compilation
에 접근하게 되면 엔진을 이용해할 수 있는 일이 많아집니다. 기존 파일을 다시 형식화하거나 파생 파일을 만들거나 완전히 새로운 Asset을 만들 수 있습니다.
filelist.md
라는 새로운 빌드 파일을 생성하는 간단한 예제 Plugin을 작성해 보겠습니다. 이 파일의 내용에는 빌드의 모든 Asset 파일이 나열됩니다. 이 Plugin은 아래와 같습니다.
|
|
Plugin의 다른 형태
Plugin은 등록된 이벤트에 따라 여러 종류로 분류할 수 있습니다. 모든 Event Hook은 레지스트리에 Plugin을 적용하는 방법을 결정합니다.
synchronous Tapable 인스턴스는 다음을 사용하여 Plugin을 적용합니다.
1applyPlugins(name: string, args: any...)1applyPluginsBailResult(name: string, args: any...)
즉, 각 Plugin 콜백은 특정 args
를 사용하여 차례로 호출됩니다. 이것은 Plugin의 가장 간단한 형식입니다. "compile"
, "this-compilation"
과 같은 많은 유용한 이벤트는 Plugin이 동기 실행할 것을 요구합니다.
waterfall Plugin을 사용하여 적용
1applyPluginsWaterfall(name: string, init: any, args: any...)
여기서 각 Plugin은 이전 Plugin의 반환값에서 args
를 사용하여 순차적으로 호출됩니다. Plugin은 실행 순서를 고려해야합니다. 실행된 이전 Plugin의 인수를 받아 들여야합니다. 첫 번째 Plugin의 값은 init
입니다. 이 패턴은 ModuleTemplate
, ChunkTemplate
과 같은webpack
템플릿과 관련된 Tapable 인스턴스에서 사용됩니다.
- asynchronous 모든 Plugin이 비동기적으로 적용될 때1applyPluginsAsync(name: string, args: any..., callback: (err?: Error) -> void)
Plugin 핸들러 함수는 모든 args
와 (err ?: Error) -> void
시그니처를 가진 콜백 함수로 호출됩니다. 핸들러 함수는 등록된 순서로 호출되며 callback
은 모든 핸들러가 호출된 후에 호출됩니다. 이것은 또한 "emit"
, "run"
과 같은 Event에 일반적으로 사용되는 패턴입니다.
async waterfall Plugin은 waterfall 방식으로 비동기로 적용됩니다
1applyPluginsAsyncWaterfall(name: string, init: any, callback: (err: Error, result: any) -> void)
Plugin 핸들러 함수는 현재 값과 (err : Error, nextValue : any) -> void
시그니처가 있는 콜백 함수로 호출됩니다. nextValue
가 호출되면 다음 핸들러의 현재 값이 됩니다. 첫 번째 핸들러의 현재 값은 init
입니다. 모든 핸들러가 적용된 후 마지막 값으로 callback
이 호출됩니다. 어떤 핸들러가 err
에 값을 전달하면, 이 에러와 함께 callback
이 호출되고 핸들러는 더 이상 호출되지 않습니다. 이 Plugin 패턴은 "before-resolve"
및 "after-resolve"
와 같은 Event에 필요합니다.
async series 비동기와 동일하지만 등록된 Plugin 중 하나라도 실패하면 Plugin이 더 이상 호출되지 않습니다.
1applyPluginsAsyncSeries(name: string, args: any..., callback: (err: Error, result: any) -> void)parallel
1applyPluginsParallel(name: string, args: any..., callback: (err?: Error) -> void)123456789101112131415161718192021222324252627282930313233343536373839applyPluginsParallelBailResult(name: string, args: any..., callback: (err: Error, result: any) -> void)``## 유용한 Plugin 패턴Plugin은 Webpack 빌드 시스템 내에서 사용자 정의를 수행할 수 있는 무제한의 기회를 부여합니다. 이를 통해 사용자 정의 Asset을 만들거나, 고유한 빌드 수정을 수행하거나, 미들웨어를 사용하면서 Webpack 런타임을 향상시킬 수 있습니다. 다음은 Plugin 작성 중에 매우 유용하게 사용되는 Webpack의 일부 기능입니다.### Asset, Chunk, 모듈 및 종속성 탐색`compilation`이 완료된 후 `compilation` 내의 모든 구조를 탐색할 수 있습니다.```javascriptfunction MyPlugin() {}MyPlugin.prototype.apply = function(compiler) {compiler.plugin('emit', function(compilation, callback) {// 각 chunk를 탐색 (build output):compilation.chunks.forEach(function(chunk) {// chunk 내의 각 모듈 탐색 (built inputs):chunk.forEachModule(function(module) {// 모듈에 포함된 각 소스 파일 경로를 탐색합니다.:module.fileDependencies.forEach(function(filepath) {// 이제 소스 구조에 대해 많은 것을 알게 되었습니다.});});// chunk에 의해 생성된 각 asset 파일을 탐색합니다.chunk.files.forEach(function(filename) {// chunk에 의해 생성된 각 파일의 asset 소스 가져 오기var source = compilation.assets[filename].source();});});callback();});};module.exports = MyPlugin;compilation.modules
: compilation의 모듈 배열 (Built 입력). 각 모듈은 소스 라이브러리에서 Raw 파일의 빌드를 관리합니다.module.fileDependencies
: 모듈에 포함된 소스 파일 경로의 배열. 여기에는 소스 JavaScript 파일 자체 (예 :index.js
) 및 필요한 모든 종속성 Asset 파일 (스타일 시트, 이미지 등)이 포함됩니다. 종속성 검토는 소스 파일이 모듈에 속하는지 확인하는데 유용합니다.compilation.chunks
: 컴파일에서 chunk 배열 (빌드 결과). 각 Chunk는 최종 렌더링 Asset의 구성을 관리합니다.chunk.modules
: Chunk에 포함되는 모듈의 배열. 확장에 따라 각 모듈의 종속성을 조사하여 청크에 공급된 Raw 소스 파일을 확인할 수 있습니다.chunk.files
: Chunk에 의해 생성된 결과 파일 이름들의 배열.compilation.assets
테이블에서 이러한 Asset 소스에 액세스할 수 있습니다.
Watch 그래프 모니터링
Webpack 미들웨어를 실행하는 동안 각 compilation
에는 Watch 대상 파일인 fileDependencies
배열과 Watch된 파일 경로를 타임스탬프에 매핑하는 fileTimestamps
가 포함됩니다. 이는 compilation
과정에서 변경된 파일을 탐지하는데 매우 유용합니다.
|
|
새로운 파일 경로를 Watch 그래프에 제공하여 파일이 변경될 때 compilation
트리거를 수신할 수 있습니다. 유효한 파일 경로를 compilation.fileDependencies
배열에 넣어 Watch에 추가하면됩니다. 참고 : fileDependencies
배열은 각 compilation
에서 다시 작성되므로 Plugin은 Watch 종속성을 각 compilation
에 넣어 Watch를 계속 유지해야합니다.
변경된 Chunk
Watch 그래프와 마찬가지로 해시를 추적하여 compilation
내에서 변경된 Chunk(또는 해당 모듈)를 모니터링하는 것도 가능합니다.
|
|
이 내용은 나중에 참고하기 위해 제가 공부하며 정리한 내용입니다.
의역, 오역, 직역이 있을 수 있음을 알려드립니다.
This post is a translation of this original article [https://webpack.js.org/contribute/writing-a-plugin/]
참고 : https://github.com/webpack/docs/wiki/How-to-write-a-plugin