-
Notifications
You must be signed in to change notification settings - Fork 442
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[译]Webpack 2 快速入门 #46
Comments
666 |
如果使用npm5.2以上或者yarn的话就没必要全局安装webpack了,直接运行 |
在多个入口文件中,按顺序打包是什么意思。
|
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
在 Webpack 2 的文档 完成之后,就会推出 Webpack 2 的 beta 版本, 但这并不意味着你知道怎么配置 Webpack 2, 却不能在项目中使用 Webpack 2.
什么是 Webpack
简单来说, Webpack 是一个针对 JavaScript 的打包工具. 然而, 随着 Webpack 日渐流行, 它逐渐演变成了前端代码的管理工具(不论是人为故意还是社区推动的).
类似Gulp的任务管理工具能处理多个不同的预处理器和编译器, 但是在所有情况下, 这都是将一个文件作为源输入, 经过处理后输出编译后的文件. 然而, Gulp 完成这些工作就像是一个任务接一个任务进行的, 没有从系统(或全局)的角度考虑如何完成任务的输入和输出. 这成了开发者的负担: 在生产环境下, 开发者需要找到任务结束的地方, 并通过合理地方式将所有的任务有序地组装在一起.
而Webpack则尝试询问一个大胆的问题来减轻开发者的负担: 假如在开发过程中的某一个部分能处理其所有的依赖会怎么样呢? 假如我们可以简单地用某种方式去写代码, 而构建程序去管理最终所必需使用到的代码又会怎么样呢?
如果过去几年你都混迹在 web 社区中, 你应该知道解决这个问题的更好方式是: 用 JavaScript 去构建. 而 Webpack 尝试通过JavaScript来解析依赖, 让构建过程变得更加简单. 但仅用于管理代码并不是Webpack设计的厉害之处, 其厉害之处在于Webpack的任务管路方式 100% 由JavaScript来完成的(利用了 Node 特性). Webpack 使你在写 JavaScript 时, 有能力从(项目的)全局角度掌控和把握整个项目.
换句话说: 你不是为Webpack写代码, 而是为你的项目写代码. 同时, webpack会自动运行(当然, 你需要写一些配置文件).
简而言之, 如果你曾经纠结过下面的任何一个问题:
那么, 你会从Webpack中收益, 因为 Webpack 能轻易地处理上述问题, 它会通过 JavaScript 来管理模块依赖和加载顺序而不是你的开发头脑. 此外, Webpack 能在服务端运行, 这意味着你能创建渐进增强的网站.
第一步
在这篇文章中, 我们将使用Yarn(
brew install yarn
)而不是npm
, 但这完全取决于你, 因为它们做的是同样的事. 在项目目录, 将运行下面的命令将 Webpack 2 添加到全局和本地项目中:安装了 Webpack 2之后, 我们需要在项目的根目录下创建一个
webpack.config.js
文件:还记得 Webpack 是怎么知道项目如何运行的吗? 它是通过读取你的代码来获知这一信息的. Webpack 的工作流如下:
context
文件夹开始entry
对应的文件import
(ES6) 或者require()
(Node) 依赖项时, 它会解析这些代码, 并且打包到最终构建里. 接着它会不断递归搜索实际需要的依赖项, 直到它到达了“树”的底部.output.path
对应的目录, 并将output.filename
的值作为最终的资源名([name]
表示使用entry
项的 key).如果
src/app.js
看起来像下面的样子(假设之前已运行了yarn add moment
):(在项目的根目录下)运行:
运行命令之后, Webpack 会输出一个
dist/app.bundle.js
文件, 同时在控制台输出当前日期. 需要注意的是, Webpack 会自动找到moment
的指向(即使你有一个moment.js
存在于目录中, 但 Webpack 默认会优先去寻找moment
的Node模块).多文件
你可以修改
entry
对象, 指定任意数量的入口文件和输出文件.多个(入口)文件一起打包
按照入口文件在数组中的顺序, 所有文件会被打包在一个
dist/app.bundle.js
里.多个(入口)文件, 多个输出(文件)
如果不想把所有打包在一个文件中, 你可以选择将多个文件打包在多个文件中. 上述例子会输出三个文件:
dist/home.bundle.js
,dist/events.bundle.js
和dist/contact.bundle.js
.自动打包
如果你将应用分开打包到多个
output
文件里(如果你的应用有非常多的 JavaScript 文件不需要在前期加载, 这样做是非常有效的), 有可能会出现很多冗余的代码, 因为 Webpack 是独立解析每个文件的依赖的. 幸运的是, Webpack 已经内置了CommonsChunk
插件来处理这个问题:加上
CommonsChunk
插件后, 任何一个模块在你的output
文件中被加载2
次(该值由minChunks
设置)及以上, 该模块就会被打包在common.js
中, 你可以在客户端缓存这些模块. 虽然这会增加额外的请求, 但这能防止客户端多次下载同一个模块.开发环境
在开发环境中, Webpack 可以提供一个开发服务器, 因为无论是你正在开发一个静态网站还是仅用于项目的前端原型设计, 它都能满足你的需要. 为启动服务器, 仅需要在
webpack.config.js
中添加一个devServer
对象:在
src
目录下创建一个带如下标签的index.html
文件:在终端运行如下命令:
开发服务器会运行在
localhost:8080
(打开你的浏览器访问该地址就能看到你的页面). 需要注意的是script
标签里的/assets
是和output.publicPath
匹配的--你可以把它命名成任何你想要的名字(如果你使用CDN, 这会很有用).Webpack 提供了热加载功能. 当你修改了 JavaScript 文件后, Webpack 会自动重新加载资源, 而不需要你手动去刷新浏览器. 但是, 任何对
webpack.config.js
文件的改变都需要重启服务器才会生效.全局方法调用
需要使用在全局作用域下的函数? 只需在
output.library
进行简单的设置就行:它会把你的打包文件捆绑在
window.myClassName
实例上. 设置了作用域之后, 你可以在文件的入口处进行调用(更多设置可以查阅文档).Loaders
到目前为止, 我只介绍了怎么使用 Webpack 处理 JavaScript 文件. 从处理 JavaScript 文件开始是非常重要的, 因为这是 Webpack 唯一能识别的语言. 实际上, Webpack 可以使用 Loaders 来处理各种通过 JavaScript 传递的任何类型的文件.
loader 可以是像
Sass
这样的预处理器, 也可以是像Babel
这样的编译器. 在 NPM 里, 它们通常被命名为*-loader
, 例如:sass-loader
或者babel-loader
.Babel+ES6
如果你想在项目里通过 Babel 使用 ES6, 首先需要安装合适的loader来编译 es6:
然后, 将loader添加到
webpack.config.js
中, 告诉 Webpack 在何处使用该loader:正则表达式
/\.js$/
会去搜索任何.js
后缀的文件, 然后通过 Babel 来加载这些文件. Webpack 依赖正则表达式来给你(对文件处理的)完全控制权---它不会限制你需要处理的文件扩展或者让你按照一定的方式来组织代码. 例如: 可能/my_legacy_code/
目录下的文件不是 ES6 写的, 你可以修改上面的test
字段为/^((?!my_legacy_code).)*\.js$/
, 这样就能排除指定的文件目录里的js文件, 剩余的(js文件)则由 Babel 处理.CSS+Style Loader
如果你的应用只需要加载 CSS, Webpack 也能满足需要. 创建一个
index.js
文件, 然后引入需要的 CSS 文件:然后会报错:
You may need an appropriate loader to handle this file type
. 在上文说过, Webpack 仅能识别 JavaScript. 因此, 需要安装合适的loader来处理 CSS 文件:然后在
webpack.config.js
中添加一条规则:Loaders会按照数组的逆序运行, 也就是说, 会先运行
css-loader
, 后运行style-loader
.你可能会注意到, 在生产环境下, CSS 会被打包到 JavaScript 文件里,
style-loader
则会把样式写在style
标签中. 此外, Webpack 通过将这些文件打包成一个文件来自动地解析所有的@import
查询(而不是依赖 CSS 的默认import
功能, 这会导致额外的 header 请求, 并且加载资源非常慢).从 JavaScript 中加载 CSS 是非常神奇的, 因为这样你可以用新的方式将 CSS 模块化. 也就是说, 可以仅通过
button.js
来加载button.css
, 这意味着如果button.js
没有用到, 其对应的 CSS 也不会被构建到生产环境中.CSS+Node 模块
我们可以使用 Webpack 里的
~
前缀来引入 Node 模块. 假如我们执行了yarn add normalize.css
, 那么就可以这么用:这样就可以充分利用 NPM 管理第三方样式库的优点---版本更新和避免复制和粘贴. 更近一步, 和 CSS 默认的
import
功能相比, 用 Webpack 打包 CSS 有明显的优势, 因为它可以为客户端减少头部请求以及缓慢的加载时间.CSS 模块
你可能已经听过 CSS 模块. 如果你通过 JavaScript 来构建 DOM 节点, 它能运行的很好. 从本质上来说, 它将你的CSS类扩展到加载它的JavaScript文件中了(了解更多).
如果你要使用 CSS模块, 可以用
css-loader
来打包 CSS 文件(yarn add --dev css-loader
):当启用了 CSS 的模块功能, 在 Node中引入CSS时去掉
~
前缀是没有任何意义的(例如:@import "normalize.css";
). 然而在你通过@import
引入自己的 CSS 文件时会碰到类似can’t find ___
的构建错误, 解决方式是在webpack.config.js
中添加一个resolve
对象, 让 Webpack 对预定的模块顺序有更好的理解.首先指定了源文件目录, 然后添加了
node_modules
目录. 这样, Webpack 在查找模块时, 会首先从源目录开始查找, (如果没找到)然后从已安装的 Node 模块中查找(你使用时, 要分别将"src"
和"node_modules"
目录替换成你的项目的源目录和Node模块目录).Sass
需要Sass? 没问题, 首先安装loader:
然后加一条规则:
这样你就能在 JavaScript 文件里通过
import
来引用.scss
或者.sass
文件, 剩下的事情交给 Webpack 来处理.将 CSS 分开打包
你可能需要处理渐进增强的情况, 也可能因某些原因需要分离 CSS 文件. 这个也很简单, 只需将配置文件中的
style-loader
用extract-text-webpack-plugin
代替就行. 例如:在本地安装该插件(需要安装2016年10月的Beta版本):
然后修改下配置文件:
运行
webpack -p
之后, 你会发现在output
指定的目录中会有一个app.bundle.css
文件. 最后, 在 HTML 文件中通过<link>
标签正常引用.用模块化的方式思考
为了最大程度的使用 Webpack, 你必须用模块化、可复用性以及可独立处理的思维方式去思考, 让每个模块把各自负责的事情做好. 这意味着类似下面这样的文件:
会变成这样:
最后编译的结果是非常简洁且可复用的代码. 每个独立的组件通过
import
来引入依赖, 再通过export
来暴露公共接口给其他模块. Babel + ES6就提供了上述特性, 并且你可以使用 JavaScript Classes 来实现更好的模块化, 而且不需要考虑运行作用域.相关阅读
参考
Getting Started with Webpack 2
Webpack2 升级指南和特性摘要
A Detailed Introduction To Webpack
The text was updated successfully, but these errors were encountered: