资讯专栏INFORMATION COLUMN

翻译 | 上手 Webpack ? 这篇就够了!

codercao / 1117人阅读

摘要:最后,我们在控制台中打印这个新数组。也可以借助简单的将其跑在浏览器上,之后可在控制台中看到同样的运行结果。使用配置文件虽然会更占位置,但与此同时增加了可读性,因为它是由写成的。例如,规定后缀的文件要先通过检查,再通过把语法转换为语法。

译者:小 boy (沪江前端开发工程师)
本文原创,转载请注明作者及出处。
原文地址:https://www.smashingmagazine....

JavaSript 模块化打包已混迹江湖许久。2009年,RequireJS 就提交了它的第一个版本,Browserify 接踵而至,随后其他打包工具也开始大行其道。最终,Webpack 从其中脱颖而出。如果你对它不甚了解,希望我的文章能让你上手这件强力打包工具。

什么是模块化打包工具?

在大多数语言(JS 的最新版本 ECMAScript 2015+ 也支持,但并非支持所有浏览器)中,你可以将代码拆分至多个文件,并且通过在业务代码中引用这些文件来使用它们包含的方法。可惜的是浏览器并不拥有这个能力。因此,模块化打包工具应运而生,它以两种形式为浏览器提供这个能力:1.异步加载模块,并且在加载结束后运行它们。2.将需要用到的文件拼凑成单一 JS 文件,最终在 HTML 中使用

假如你一直跟着做的话,example5 分支便在此结束。不同插件传入的参数或者配置项也大异其趣,其原因在于插件种类繁多且涵盖范围广阔,但殊途同归的是,他们最终都会被添加到 webpack.config.jsplugins 数组中。同样,也有其他方式可以处理 HTML 页面的生成和文件名填充,一旦你开始为打包后的文件添加清缓存哈希值(cache-busting hashes)后缀,这些事情就会变得非常简单。

观察示例仓库,你会发现有一个 example6 分支,在该分支里我通过添加插件实现了 JS 代码压缩,但这不是必须的,除非你想改动 UglifyJS 配置。如果你不爽 UglifyJS 的默认配置,可将仓库切换 (check out)至该分支下(只需要查看 webpack.config.js )去找到如何使用该插件并加以配置。但如果默认配置正合你意,你只需要在命令行运行 webpack 时传入 -p 参数。该参数是 production 的简写,与使用 --optimize-minimize--optimize-occurence-order 参数的效果一样,前者用以压缩 JS 代码,后者用以优化已引入模块的顺序,着眼于稍小的文件尺寸和稍快的执行速度。在示例仓库完成一段时间后我才知道 -p 这个参数,所以我决定保存该插件示例,可以用来提醒你还有更简单的方法(除了添加插件之外)。另一可供使用的快捷命令参数是 -d-d 会展示更多 Webpack 打印出的信息,并且可不借助其他参数生成资料图(source map)。还有很多其他命令行快捷参数可供使用。

懒加载数据块

懒加载(lazy-loading)模块是我在 RequireJS 中用得舒适但在 Browserify 中难以工作的模块。一个颇具规模的 JS 文件固然可以从减少网络请求中受益,但也几乎坐实了在一次会话中,某些用户不必用到的代码会被下载下来。

Webpack 可以将打包文件拆分成可被懒加载的若干块(chunks),而且还不需要任何配置。你仅需要从两种书写方式中挑一种来书写代码,剩下的则交给 Webpack。这两种方式其一基于 CommonJS ,其二则基于 AMD。如果使用前者懒加载,需要这样写:

require.ensure(["module-a", "module-b"], function(require) {
    var a = require("module-a");
    var b = require("module-b");
    // …
});

require.ensure 需要确保模块是可用的(但并非运行模块),然后传入一个由模块名构成的数组,接着传入一个回调函数(callback)。真正想要在回调函数里使用模块,你需要显式 require 数组里传入的相应模块。

私以为这种方式相麻烦,所以,我们来看 AMD 的写法。

require(["module-a", "module-b"], function(a, b) {
    // …
});

AMD 模式下,使用 require 函数,传入包含依赖模块名的数组,接着再传入回调函数。该回调函数的参数就是依赖模块的引用,它们的排列顺序与依赖模块在数组中的排列顺序相同。

Webpack 2 同时也支持 System.import,其借助于 promises 而非回调函数。尽管将回调内容包裹在 promise 下并非难事,但我仍以为该提升非常有用。不过需要注意的是, System.import 现已过时,较新的规范推荐使用 import()。不过,这里告诫一下, Babel (以及 TypeScript)会在你使用System.import的时候抛出语法异常。你可以借助于 babel-plugin-dynamic-import-webpack 插件,但该插件将会将其转化为 require.ensure,而不是让 Babel 合法处理新 import 或者任之由 Webpack 处置。我认为 AMD 或 require.ensure 在很久之后才会被弃置,且 Webpack 直到第三个版本才会支持 System.import ,那还远着呢,所以用你顺眼的那个就好了。

扩充我们的代码,令其停滞两秒,然后再将 Handlebars 模板懒加载进来并输出到屏幕上。为此,我们移除顶部 import 模板的语句,然后将最后一行包裹到 setTimeout 和 AMD 模式的 require 中引入模板。

运行 npm start ,你会发现生成了另外一个名为 1.bundle.js 的资源文件(asset)。在浏览器打开该页面,然后在开发者工具中监听网络流量,2秒之后你会发现新的资源文件最终被加载并且运行了。以上这些实现起来并不困难,但提升用户体验可不止一点。

注意,这些二级打包文件(sub-bundles)或曰数据块(chunks),内部囊括了他们的所有依赖模块(dependencies),但不包含其主数据块(parent chunks)已引入的依赖模块。(你可以有多个入口文件,每个都懒加载一个数据块,因此该数据块在其主数据块中加载的依赖模块也会不同。)

创建公共库数据块 (Vendor Chunk)

我们再说一个优化的点:公共库数据块。你可以定义一个多带带用以打包的 bundle,该 bundle 中存放不常改动的 “common” 库或第三方代码。该策略可使用户独立缓存你的公共库文件,以区别于业务代码,以便在你迭代应用时让用户无需重新下载该库文件。

为此,我们使用 Webpack 官方插件:CommonsChunkPlugin。它已附带在 Webpack 中,所以我们无需安装。仅对 webpack.config.js 稍作修改即可:

var HtmlwebpackPlugin = require("html-webpack-plugin");
var UglifyJsPlugin = require("webpack/lib/optimize/UglifyJsPlugin");
var CommonsChunkPlugin = require("webpack/lib/optimize/CommonsChunkPlugin");

module.exports = {
    entry: {
        vendor: ["babel-polyfill", "lodash"],
        main: "./src/main.js"
    },
    output: {
        path: "./dist",
        filename: "bundle.js"
    },
    module: {
        rules: [
            {
                test: /.jsx?$/, loader: "babel-loader", exclude: /node_modules/,
                options: { plugins: ["transform-runtime"], presets: ["es2015"] }
            },
            { test: /.hbs$/, loader: "handlebars-loader" }
        ]
    },
    plugins: [
        new HtmlwebpackPlugin({
            title: "Intro to webpack",
            template: "src/index.html"
        }),
        new UglifyJsPlugin({
            beautify: false,
            mangle: { screw_ie8 : true },
            compress: { screw_ie8: true, warnings: false },
            comments: false
        }),
        new CommonsChunkPlugin({
            name: "vendor",
            filename: "vendor.bundle.js"
        })
    ]
};

我们在第三行引入该插件。此后,在 entry 部分修改配置,将其换成了一个对象字面量(literal),用以指定多入口。vendor 入口记录了会在公共库数据块中——这里包含了 polyfill 和 Lodash ——被引入的库并将我们的主要入口放置在 main 入口里。接着,我们仅需将 CommonsChunkPlugin 添加到 plugins 部分,指定 “vendor” 数据块作为该插件生成数据块的索引,同时指定 vendor.bundle.js 文件用以存放公共库代码(译者注:这里插件配置中的 name: "vendor" 对应 entry 中的 vendor 入口,入口数组中指定的依赖模块即最终存放于 vendor.bundle.js 文件中的依赖模块)。

通过指定 “vendor” 数据块,该插件将拉取此数据块所有的依赖模块,并将其存放于公共库数据块內,这些依赖模块在一个多带带入口文件里被指定。如果不在入口对象字面量中指定数据块名,插件会基于多入口文件之间公用的依赖模块来生成独立文件。

运行 Webpack ,你将看到3份 JS 文件:bundle.js, 1.bundle.jsvendor.bundle.js。如果愿意的话也可以运行 npm start 命令来在浏览器中查看结果。看起来 Webpack 甚至会把自身加载不同模块的主要代码放进公共库数据块,此举极为实用。

至此我们结束了 example8 分支之旅,同时本篇教程也接近尾声。我所谈颇多,但仅让你对 Webpack 的能力浅尝辄止。Webpack 实现了更简便的 CSS module、清缓存、图片优化等等很多事情——多到即便书巨著一本,我也无法说穷道尽,且在我成书之前,大多数已写的内容也将被更新替代。So,尝试一下 Webpack 吧,且告诉我它有没有提升工作流。祝吾主保佑,编程愉快!


iKcamp原创新书《移动Web前端高效开发实战》已在亚马逊、京东、当当开售。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/85056.html

相关文章

  • JS正则表达式入门,看这篇够了

    摘要:如果遇到非常的复杂的匹配,正则表达式的优势就更加明显了。关于正则表达式书写规则,可查看,上面说的很清楚了,我就不贴出来了。替换与正则表达式匹配的子串,并返回替换后的字符串。结语正则表达式并不难,懂了其中的套路之后,一切都变得简单了。 前言 在正文开始前,先说说正则表达式是什么,为什么要用正则表达式?正则表达式在我个人看来就是一个浏览器可以识别的规则,有了这个规则,浏览器就可以帮我们判断...

    wenzi 评论0 收藏0
  • 2017-08-31 前端日报

    摘要:前端日报精选从化的探讨体会团队设计思想导致的跨站漏洞在饿了么前端的实践还是你应该选择哪一个前端框架上手这篇就够了中文网格布局入门上最流行的项目众成翻译的入门教程众成翻译开发,在中配置众成翻译组件间的样式污染掘金核心模块之 2017-08-31 前端日报 精选 从 setState promise 化的探讨 体会 React 团队设计思想jQuery导致的XSS跨站漏洞Weex 在饿了么...

    liuhh 评论0 收藏0
  • 库,组件,框架 - 收藏集 - 掘金

    摘要:哈哈,我理解,架构就是骨架,如下图所示译年月个有趣的和库前端掘金我们创办的使命是让你及时的了解开发中最新最酷的趋势。 翻译 | 上手 Webpack ? 这篇就够了! - 掘金译者:小 boy (沪江前端开发工程师) 本文原创,转载请注明作者及出处。 原文地址:https://www.smashingmagazine.... JavaSrip... 读 Zepto 源码之代码结构 - ...

    tommego 评论0 收藏0
  • Lombok 看这篇够了

    摘要:注解在类上为类提供一个全参的构造方法,加了这个注解后,类中不提供默认构造方法了。这个注解用在类上,使用类中所有带有注解的或者带有修饰的成员变量生成对应的构造方法。 转载请注明原创地址:http://www.54tianzhisheng.cn/2018/01/07/lombok/ showImg(http://ohfk1r827.bkt.clouddn.com/blog/180107/7...

    LeanCloud 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<