Webpack:Webpack 内部是如何工作的? [英] Webpack: how does Webpack work internally?

查看:25
本文介绍了Webpack:Webpack 内部是如何工作的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

据我所知,Webpack 是一个用于组织项目中资产的工具.然而,我不明白它内部是如何工作的,看起来有点神奇.

  • 是否有某种运行时引擎解析模块或依赖项?
  • 它是在服务器上运行还是在客户端浏览器中运行?
    • 如果它在服务器上运行,它是否必须在某种webpack-*-server上运行?
    • 如果它在浏览器中运行,它如何构建模块 <-> 加载器 <-> 映射?它是如何发送到浏览器的?

解决方案

Webpack - The Why and the How

不要让自己被 Webpack 所做的所有花哨的东西弄糊涂了.那么什么是 Webpack?好吧,它是一个模块捆绑器,我们开始了.开个玩笑,这根本不会告诉初学者.我相信为什么对获得 webpack 很重要,因此这个答案的大部分内容将集中在这一点上.

Webpack 的核心允许我们在浏览器中使用 javascript 模块,方法是将多个文件和资产组合成一个大文件,如下图所示,来自

诸如将 es6/7 编译为 es5 或允许我们使用 css 模块等所有额外的亮点都是 Webpack 提供给我们的很好的额外.

Webpack 插件和附加功能的强大生态系统使 Webpack 看起来很混乱,因为它似乎做了很多事情.虽然通过插件为我们提供的附加功能很棒,但我们需要专注于 Webpack 存在的核心原因 - 模块捆绑.因此,加载器和插件超出了 Webpack 帮助解决的基本问题的高级讨论范围.

Webpack 是一个命令行工具,用于创建资产包(代码和文件).Webpack 不在服务器或浏览器上运行.Webpack 获取您所有的 javascript 文件和任何其他资产,然后将其转换为一个巨大的文件.

这个大文件然后可以由服务器发送到客户端的浏览器.请记住,浏览器和服务器并不关心这个大文件是使用 Webpack 生成的,它只是像对待任何其他文件一样对待它.

webpack-dev-server vs webpack cli

webpack-dev-server 是一个与上述 webpack cli(命令行工具)完全不同的工具.它是一个运行在 node/express 上的开发服务器.当这个服务器运行时,我们从这个开发服务器上的一个端口加载我们的应用程序,我们可以在开发我们的应用程序时访问其他功能,使我们的生活更轻松,例如热模块重新加载和自动捆绑(运行 webpack cli 以自动捆绑一个文件变化).热模块重新加载的优点是我们可以保持应用程序运行并注入在运行时编辑的文件的新版本.因此,我们可以在不丢失整个应用程序状态的情况下查看应用程序中某些文件的更改情况.

原因

传统服务器渲染应用

传统上,应用程序已在服务器端呈现.这意味着客户端向服务器发出请求,所有逻辑都在服务器上.服务器向客户端吐出一个静态 html 页面,这就是他们在浏览器中看到的内容.这就是为什么每当您在旧的服务器端渲染应用程序中导航时,您都会看到页面在刷新时闪烁.

单页应用 - SPA

然而,如今单页应用程序风靡一时.在单页应用程序中,我们的应用程序在一个 url 内窗口化,我们永远不需要刷新.对于用户来说,这被认为是一种更好的体验,因为它无需刷新就感觉更流畅.在 SPA 中,如果我们想从主页导航到登录页面,我们将导航到登录页面的 url.然而,与传统的服务器端呈现的页面不同,当客户端的浏览器发出此请求时,页面不会刷新.相反,应用程序将动态更新自身以显示登录内容.尽管这在我们的单页应用程序中看起来像是一个单独的页面,但我们的应用程序只是针对不同的页面动态更新.

动态 SPA 意味着浏览器中的代码更多

因此,在具有所有这些动态内容的 SPA 中,浏览器中有更多的 javascript 代码.当我们说动态时,我们指的是以 javascript 形式存在于客户端浏览器中的逻辑量.我们的服务器端呈现的应用程序会吐出非动态的静态页面.在生成静态页面时,所有动态都发生在服务器中,但是一旦它访问浏览器,它就相对静态(其中没有很多 javascript)

方法

管理大量新的浏览器逻辑,即更多的 Javascript

Webpack 的主要设计目的是应对客户端中越来越多的 javascript 的新兴趋势.

好的,那么我们在浏览器中有很多 javascript 为什么这是一个问题?

我们需要在客户端将代码拆分成多个文件,以便应用程序更易于使用

好吧,我们把它放在哪里?我们可以把它全部放在一个大文件中.但是,如果我们这样做,那么深入了解所有部分的工作原理将是一场噩梦.相反,我们需要根据每个块的功能将这一大块代码拆分成更小的块——即将代码拆分到多个文件中.

您可能知道,当我们谈论制作模块化的东西"时,将大事物分解为按功能分组的较小事物.您可能会想,为什么不将大块代码拆分成小块并完成它.问题是客户端并不神奇地知道哪些文件从其他文件中导入了东西.因此,我们可以在没有 Webpack 的情况下拥有多个隔离的文件,但是 应用程序将无法正常工作,因为它更有可能在大块代码中大部分代码将依赖于大块中的其他部分代码大块工作.

我们需要像 Webpack 或它的替代品之一(browserify)来创建模块系统.在服务器端,Node 有一个内置的模块解析器,您可以在其中要求"模块.但是,浏览器不附带此功能.

但是,如果我们有多个文件,其中一些文件会相互导入,我们需要一种方法来了解哪些文件相互依赖或依赖.Webpack 允许我们在前端使用 JavaScript 模块,方法是从入口点遍历文件,然后映射它们的依赖项.将入口点视为相互依赖的文件链中层次结构的顶部.

Webpack 中的模块/依赖解析

通过绘制依赖关系图,Webpack 能够以正确的顺序异步和并行加载不同的模块.Webpack 内部有自己的解析器,用于计算不同模块之间的依赖关系图.webpack 文档指出

<块引用>

resolver 帮助 webpack 找到需要的模块代码包含在每个这样的 require/import 语句的包中.

然后文档解释了解析器根据 Webpack 捆绑的文件中的导入引用的路径类型采用不同的方法.

<块引用>

解析过程非常简单,可以区分三个请求类型:

  • 绝对路径:require("/home/me/file"), require("C:\Home\me\file")
  • 相对路径:require("../src/file"), require("./file") 模块路径:
  • require("module"), require("module/lib/file")

As far as I could understand, Webpack is a tool for organizing assets in the project. However, I don't understand how it works internally and it seems a bit magical.

  • Is there some kind of runtime engine resolving modules or dependencies?
  • Does it run on the server or in the client browser?
    • If it runs on the server, does it have to run on a some kind of webpack-*-server?
    • If it runs in the browser, how does it build module <-> loader <-> map? How is it sent to the browser?

解决方案

Webpack - The Why and the How

Don't let yourself get confused by all the fancy stuff Webpack does. What is Webpack then? Well its a module bundler, there we go. Just kidding, this doesn't tell the beginner very much at all. I believe that the why is important to getting webpack so the bulk of this answer will focus on that.

At its core Webpack allows us to use javascript modules within our browser by taking multiple files and assets and combining them into one big file as shown below in this image from the new docs for Webpack 2.

All the extra shiny things such as compiling es6/7 to es5 or allowing us to use css modules are just nice extras afforded to us by Webpack.

The powerful ecosystem of Webpack plugins and extras makes Webpack seem confusing as it appears to do so much. While the additional features afforded to us through plugins is great we need to stay focused on the core reason Webpack exists - module bundling. Therefore loaders and plugins are outside the scope of this high level discussion on the fundamental problem that Webpack helps solve.

Webpack is a command line tool to create bundles of assets (code and files). Webpack doesn't run on the server or the browser. Webpack takes all your javascript files and any other assets and transforms then into one huge file.

This big file can then be sent by the server to a client's browser. Remember the browser and server don't care that this big file was generated using Webpack it just treats it like any other file.

webpack-dev-server vs webpack cli

webpack-dev-server is a fundamentally different tool from the webpack cli (command line tool) described above. It is a development server that runs on node / express. When this server is running we load our app from one of the ports on this development server and we can access additional features while developing our app that makes our life easier such as hot module reloading and autobundling (runs webpack cli to bundle automatically when a file changes). The advantage of hot module reloading is that we can keep the app running and inject new versions of the files that are edited during runtime. Therefore we can see what changes to some files in the application look like without losing the state of the whole app.

The Why

Traditional Server Rendered Apps

Traditionally apps have been server side rendered. This means that a request is made by a client to a server and all the logic is on the server. The server spits out a static html page back to the client which is what they see in their browser. This is why whenever you navigate in old server-side rendered apps you will see the page flash as it refreshes.

Single Page Apps - SPAs

However nowadays single page applications are all the rage. On a single page application our app is windowed within one url and we never need to refresh. This is considered a nicer experience for the user as it feels slicker not having to refresh. In SPAs if we want to navigate from the home to say the signin page we would navigate to the url for the signin page. However unlike traditional server side rendered pages when the client's browser makes this request the page will not refresh. Instead the app will dynamically update itself in order to show the signin content. Although this looks like a separate page in our Single Page Application our app just dynamically updates for different pages.

Dynamic SPAs mean more code in the browser

So in SPAs with all this dynamic content there is way more javascript code that is in the browser. When we say dynamic we are referring to the amount of logic that lives within the client's browser in the form of javascript. Our server side rendered apps spit out static pages that are not dynamic. The dynamism all happens in the server while generating the static page but once it hits the browser it is relatively static (there isn't a lot of javascript in it)

The How

Managing this new abundance of browser logic i.e more Javascript

Webpack was primarily designed to deal with the emerging trend of having more and more javascript in the client.

Ok, so what we have a lot of javascript in the browser why is this a problem?

We need to split the code into multiple files on the client so the app is easier to work on

Well, where do we put it all? We can put it all in one big file. However, if we do this it will be a nightmare to wade through it and understand how all the parts work. Instead, we need to split this one huge chunk of code into smaller chunks according to the function of each chunk - i.e splitting the code across multiple files.

As you probably know decomposing large things into smaller things grouped by function is what we mean when we talk about 'making something modular'. You may be thinking why not just split the big chunk of code into little chunks and be done with it. The problem is the client doesn't magically know which files import stuff from other files. So we could have multiple isolated files without Webpack but the app won't work properly as it is more likely than not that within the big chunk of code most of the code within it will rely on other parts of code in the big chunk to work.

We need something like Webpack or one of its alternatives (browserify) to create a module system. On the server side Node has a built-in module resolver where you can "require" modules. However browsers do not come with this functionality.

However if we have multiple files some will import from each other and we need a way of knowing which files rely or are dependent on each other. Webpack allows us to use JavaScript modules on the front end by traversing through the files from an entry point and then mapping their dependencies. Think of the entry point as the top of the hierarchy in a chain of files that are dependent on each other.

Module/ Dependency resolution in Webpack

By mapping out a graph of the dependencies Webpack is able to load the different modules in the correct order asynchronously and in parallel. Internally Webpack has its own resolver for figuring out the dependency graph between different modules. The webpack docs state that

The resolver helps webpack finds the module code that needs to be included in the bundle for every such require/import statement.

Then the docs explain that the resolver takes a different approach according to the type of path that is referenced by imports in the files that Webpack is bundling.

The resolving process is pretty simple and distinguishes between three types of requests:

  • absolute path: require("/home/me/file"), require("C:\Home\me\file")
  • relative path: require("../src/file"), require("./file") module path:
  • require("module"), require("module/lib/file")

这篇关于Webpack:Webpack 内部是如何工作的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆