Skip to content
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

「3」前端开发利器 webpack #4

Open
BuptStEve opened this issue Dec 30, 2015 · 0 comments
Open

「3」前端开发利器 webpack #4

BuptStEve opened this issue Dec 30, 2015 · 0 comments

Comments

@BuptStEve
Copy link
Owner

BuptStEve commented Dec 30, 2015

零、前言

在编写构建前端项目时,以下这些需求想必十分常见:

  1. html/css/js 代码的预编译:
    • Jade, Ejs...
    • Sass, Less, Stylus...
    • Dart, CoffeeScript, TypeScript, ES6/7...
  2. 拯救你的 F5 或者 Command/Ctrl + R(即自动监听、编译并刷新浏览器)
  3. 发布时的代码压缩、混淆,图片的压缩和 base64 嵌入

以上这些「体力♂活儿」显然不能自己浪费时间手动完成,所以优雅的解决方式就是:自动化构建工具~!

话说我最早了解到前端自动化构建工具,是通过慕课网学习的时候看到的 grunt 教程,随意浏览了点儿发现上手有点儿难 (:зゝ∠) 同时也没有什么需求就没有学下去。

然后学习了 less/sass/stylus 等预编译语言,先是使用了 koala 进行 less 文件的编译。之后又有了「拯救 F5」的需求,觉得再使用 livereload 这样不够绅士(´・ω・`)。于是开始学习 gulp, gulp 是基于 Unix 的哲♂学,即

Do one thing and do it well.

类似于 Unix 的管道命令(pipe:| ),gulp 基于 Node.js 中的 stream 机制。Gulp 的每个插件从 stream 中读取输入,做一些处理,再输出到 stream 中。同时使用 browser-sync 插件能够解决我的重复刷新的繁重劳动。

无奈前端变化太快_(:зゝ∠)_,使用 gulp 没多久。通过 vue.js 一个 MVVM 框架,知道了 webpack 这一新的前端自动化构建工具。使用 webpack 可以方便地将 *.vue文件编译打包到工程中,并且 react 的大部分项目也使用 webpack 进行构建。那么问题来了,webpack 究竟靠什么火起来了呢?

一、webpack

1.1. 为什么选择 webpack ? 参考链接

a. 模块化

首先要明确:随着前端越来越「重」,项目变得越来越大,团队人数增加、功能增加地越多,势必引起出错、依赖情况的出现。那么想想服务器端、桌面大型程序等是怎么做的呢?

答案只有一个:模块化开发!

然而浏览器本身并不提供模块管理的机制(ES6 终于引入 Module),为了调用各个模块,有时不得不在网页中,加入一大堆script标签。这样就使得网页体积臃肿,难以维护,还产生大量的HTTP请求,拖慢显示速度,影响用户体验。

在此对于模块化就不继续展开了...Require.js/Sea.js/Common.js/AMD/CMD/ES6...etc.

b. 代码传输

明确了模块化开发这一前提之后,那么新的问题又来了...模块化之后的文件怎么从服务器传递到客户端(浏览器)?

有两种「极端」的方式

  • 每一个请求传送一个模块(类似于一堆的 <srcipt> 标签...)
  • 一个请求传送所有模块(例如 browserify 的打包方式)

这两种方式方式各有优缺点:

  1. 一个请求一个模块
    * 优点:只加载需要的模块;
    * 缺点:大量请求会使得启动缓慢...
  2. 一个请求所有模块
    * 优点:请求数少,等待时间少;
    * 缺点:不需要的模块同样被传送了...

因此,在大多数的情况下最佳实践应该是一个折中的方案:

在编译所有模块时,将模块细分成为多个小的 batches(chunks),于是我们分解得到了许多请求。模块的 chunks 初始状态时并没有全部加载,只在需要的时候发起请求。因此初始请求不会包含所有的代码,显然加载的代码量更小,速度更快。

其中关键的「分割点」即 chunks 的划分边界,是取决于开发者并且是可选的。

c. 模块热替换(HMR)

此外还有一个重要原因:webpack 支持模块热替换(HMR)(例如 react-hot-loader

针对浏览器自动刷新,LiveReload 和 Browser-sync 是两款常用的工具,然而 HMR 更进了一步。我们知道 React 出现的原因之一就是积累用户在浏览器中的状态,而 HMR 能够在修改代码保存之后仍然保存之前的状态,就是俗称的「热替换」。

1.2. 怎么使用 webpack?

了解了为什么(why)之后,接着学习怎么做(how)。

a. webpack 的安装

  • 首先使用 npm 全局安装 webpack:
$ npm i(nstall) -g webpack
  • 接着局部安装 webpack:
$ npm i(nstall) --save-dev webpack

b. webpack 的配置

webpack 配置的本质就是:一个配置的 Object。

因此有两种使用方法配置 webpack:

  • 一种是 Cli(即 Command Line Interface)方法:读取 webpack.config.js 文件;
  • 另一种是 Node.js API 的方法:传递配置对象作为参数。

前端一般使用第一种,即配置 webpack.config.js 文件,简单例子如下:

// webpack.config.js
module.exports = {
    entry: './main.js',
    output: {
        filename: 'bundle.js'
    }
};

就是设置入口、出口文件,炒鸡简单有木有~

接着我们需要进行一些预编译工作,例如把 CoffeeScript 或 ES6 的代码编译为 ES5 的 JavaScript,例子如下:

// webpack.config.js
module.exports = {
    entry: './main.js',
    output: {
        filename: 'bundle.js'
    },
    module: {
        loaders: [{
            test: /\.coffee$/,
            loader: 'coffee-loader'
        }, {
            test: /\.js$/,
            loader: 'babel-loader'
        }]
    }
};

只需要加入 loader,loader 中的 test 表示哪些文件需要经过 loader 进行处理。

对于 css 和 图片资源同样也有 loader,这样就可以像引用 js 一样在代码中引用,例如:

require('./bootstrap.css');
require('./myapp.less');

var img = document.createElement('img');
img.src = require('./glyph.png');

loader 的编写类似于之前的例子:(!用于链式操作,且从右往左执行)

// webpack.config.js
module.exports = {
    entry: './main.js',
    output: {
        path: './build', // This is where images AND js will go
        publicPath: 'http://mycdn.com/', // This is used to generate URLs to e.g. images
        filename: 'bundle.js'
    },
    module: {
        loaders: [{
                test: /\.less$/,
                loader: 'style-loader!css-loader!less-loader'
            }, // use ! to chain loaders
            {
                test: /\.css$/,
                loader: 'style-loader!css-loader'
            }, {
                test: /\.(png|jpg)$/,
                loader: 'url-loader?limit=8192'
            } // inline base64 URLs for <=8k images, direct URLs for the rest
        ]
    }
};

last but not the least: 添加 webpack-dev-server 作为实时代码更新
安装完成后只需添加两行代码到 webpack.config.js 中:

module.exports = {
    ...
    entry: [
        'webpack-dev-server/client?http://0.0.0.0:8080',
        'webpack/hot/only-dev-server',
        './app/main.js'
    ],
    ...
};

并且在 package.json 中的 scripts 添加一行代码:

{
    "scripts": {
        "dev": "webpack-dev-server --devtool eval --progress --colors --hot --content-base build"
    },
}

这样在日常开发中只需要执行:

$ npm run dev

在浏览器中访问 http://localhost:8080 即可看到编译结果,并且更改代码后能够自动刷新。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant