Webpack은 패키징을 어떻게 구현하나요? 다음 기사는 Webpack 패키징 원칙에 대한 심층적인 이해를 제공할 것입니다. 도움이 되기를 바랍니다.
프론트 엔드 "공성 사자"로서 Webpack은 너무 많은 일을 할 수 있습니다. Webpack은 모든 리소스(JS, TS, JSX, 이미지, 글꼴, CSS 등 포함)를 패키징할 수 있습니다. 이를 종속 관계에 배치하면 종속성을 참조하여 필요에 따라 리소스를 사용할 수 있습니다. Webpack은 프런트 엔드에서 다양한 파일 리소스를 변환하고 복잡한 모듈 종속성을 분석하는 훌륭한 작업을 수행했습니다. 또한 로더를 사용자 정의하고 자체 리소스를 자유롭게 로드할 수 있습니다. 그렇다면 Webpack은 어떻게 패키징을 구현합니까? 오늘 와서 구경해 보세요.
1. require란?
필요할 때 가장 먼저 떠오르는 것은 가져오기입니다.
– require는 런타임 호출이므로 이론적으로 코드의 어느 곳에서나 사용할 수 있습니다. – import는 컴파일 타임 호출이므로 파일 시작 부분에 배치해야 합니다.
Webpack을 사용하여 컴파일할 때 import를 require로 변환하는 데 바벨을 사용합니다. (), AMD 및 CMD도 참조하기 위해 require 메소드를 사용합니다.
예:
var add = require('./a.js'); add(1,2)
간단히 말하면 require는 실제로 함수이고 참조된
는 함수의 매개변수일 뿐입니다../a.js
여기서 내보내기를 객체로 생각하면
MDN 내보내기구체적인 사용법을 볼 수 있습니다. 이제 require와 내보내기를 이해했으므로 패키징을 시작할 수 있습니다.
모든 브라우저에서 require 내보내기를 실행할 수 있는 것은 아닙니다. 코드의 정상적인 작동을 보장하려면 require 및 내보내기를 직접 구현해야 합니다. 패키지된 코드는 자체 실행 함수이며, 매개변수에는 종속성 정보가 포함되어 있으며 실행된 함수 본문은 eval을 통해 코드를 실행합니다.
전체 디자인 다이어그램은 다음과 같습니다.
1단계: 구성 파일 작성구성 파일은 후속 세대를 위한 패키지 항목 항목과 패키지 종료 출력을 구성합니다. 문서가 준비되었습니다.
const path = require("path"); module.exports = { entry: "./src/index.js", output: { path: path.resolve(__dirname, "./dist"),//打包后输出的文件地址,需要绝对路径因此需要path filename:"main.js" }, mode:"development"
2단계: 모듈 분석
전체 아이디어: fs 파일을 사용하여 항목 파일을 읽고 AST를 통해 가져오기 종속 파일의 경로를 얻는 것으로 요약할 수 있습니다. 여전히 종속성이 있습니다. 종속성 분석이 명확하고 맵에서 유지될 때까지 반복됩니다.
상세한 해체: AST가 이 기능으로 탄생했기 때문에 왜 AST를 사용하는지 궁금해하는 사람들도 있습니다. ImportDeclaration을 사용하면 가져오기 구문을 빠르게 필터링할 수 있습니다. 물론 일반 매칭도 가능합니다. 파일을 읽은 후 문자는 단 하나입니다. 문자열, 멋진 정규식을 작성하여 파일 종속성 경로를 얻지만 충분히 우아하지 않습니다.
1단계: 다음과 같이 새 index.js, a.js, b.js 종속성을 만듭니다.import { str } from "./a.js"; console.log(`${str} Webpack`)
a.js 파일
import { b} from "./b.js" export const str = "hello"
b.js 파일
export const b="bbb"
: AST의 @babel/parser를 사용하여 파일에서 읽은 문자열을 AST 트리로 변환하고, 구문 분석을 위해 @babel/traverse를 사용하고, ImportDeclaration을 사용하여 가져오기를 필터링하여 파일 종속성을 찾습니다. const content = fs.readFileSync(entryFile, "utf-8");
const ast = parser.parse(content, { sourceType: "module" });
const dirname = path.dirname(entryFile);
const dependents = {};
traverse(ast, {
ImportDeclaration({ node }) {
// 过滤出import
const newPathName = "./" + path.join(dirname, node.source.value);
dependents[node.source.value] = newPathName;
}
})
const { code } = transformFromAst(ast, null, {
presets: ["@babel/preset-env"]
})
return {
entryFile,
dependents,
code
}
종속성 분석을 위해 재귀 또는 루프를 사용하여 파일을 하나씩 가져옵니다. 여기서 루프가 모든 종속성을 분석할 수 있는 이유는 다음과 같습니다. 모듈의 길이에 주의하세요. 종속성.modules.push 새 종속성이 있으면 module.length가 변경됩니다.
for (let i = 0; i <p></p><p>3단계: WebpackBootstrap 함수 작성 + 출력 파일 생성<strong><span style="font-size: 18px;"></span><p><strong>编写</strong> <strong>WebpackBootstrap</strong> <strong>函数</strong>:这里我们需要做的首先是 WebpackBootstrap 函数,编译后我们源代码的 import 会被解析成 require 浏览器既然不认识 require ,那我们就先声明它,毕竟 require 就是一个方法,在编写函数的时候还需要注意的是作用域隔离,防止变量污染。我们代码中 exports 也需要我们声明一下,保证代码在执行的时候 exports 已经存在。</p> <p><strong>生成输出文件</strong>:生成文件的地址我们在配置文件已经写好了,再用 fs.writeFileSync 写入到输出文件夹即可。</p> <pre class="brush:php;toolbar:false"> file(code) { const filePath = path.join(this.output.path, this.output.filename) const newCode = JSON.stringify(code); // 生成bundle文件内容 const bundle = `(function(modules){ function require(module){ function pathRequire(relativePath){ return require(modules[module].dependents[relativePath]) } const exports={}; (function(require,exports,code){ eval(code) })(pathRequire,exports,modules[module].code); return exports } require('${this.entry}') })(${newCode})`; // WebpackBoostrap // 生成文件。放入dist 目录 fs.writeFileSync(filePath,bundle,'utf-8') }
第四步:分析执行顺序
我们可以在浏览器的控制台运行一下打包后的结果,如果能正常应该会打印出 hello Webpack。
通过以上的分析,我们应该对 Webpack 的大概流程有基本的了解,利用 AST 去解析代码只是本次演示的一种方式,不是 Webpack 的真实实现,Webpack 他自己有自己的 AST 解析方式,万变不离其宗都是拿到模块依赖,Webpack 生态是很完整,有兴趣的童鞋可以考虑以下三个问题:
更多编程相关知识,请访问:编程视频!!
위 내용은 웹팩의 패키징 과정과 원리에 대한 심층 분석의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!