使用webpack工程化已有项目

前言

公司项目随着业务扩展和功能的增加,网站前端部分出现以下现状:

  • 前端文件过于碎片化,打开网站需要加载几十个js文件,严重影响打开速度。

  • 缺乏依赖管理工具,增入新功能时要手动引入文件,经常造成依赖丢失、错乱。

现使用 webpack 对项目的前端结构进行工程化整理。

webpack是当前最流行的模块加载器兼打包工具,它能把各种资源,例如JS(含 JSX )、样式(含less/sass)、图片等都作为模块来使用和处理。

webpack 的优势

其优势主要可以归类为如下几个:

  • webpack 是以 commonJS 的形式来书写js,但对 AMD/CMD 的支持也很全面,方便旧项目进行代码迁移。

  • 能被模块化的不仅仅是 JS 了。

  • 串联式模块加载器以及插件机制,让其具有更好的灵活性和扩展性,例如提供对TypeScript、ES6的支持;

  • 开发便捷,能替代部分 grunt/gulp 的工作,比如打包、压缩混淆、图片转base64等。

  • 开发时在内存中完成打包,性能更快,完全可以支持开发过程的实时打包需求。

普通jq项目的改造

原先的结构

1
2
3
4
// moduleA
window.xxx = {
// some thing
}

改造后,同时兼容 直接引入文件 和 commonJS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// moduleA
(function(factory){

if (typeof module === "object" && typeof module.exports === "object") {
module.exports = factory(require('jquery'), require('./moduleB'));
}
else {
window.xxx = factory(jQuery, B)
}

})(function($, B){

return xxx;
})

angular项目的改造

1
2
3
4
5
6
// controller1.js
module.exports = ngModule=>{
ngModule.controller('controller1',['$scope','FontFaceOnload', ($scope, FontFaceOnload)=> {
// ...
}])
}

多页面结构

针对网站是多页面应用的情况,为每个页面提供一个入口文件,每个页面分别加载相应的依赖和逻辑。

1
2
3
4
5
6
7
8
9
10
11
12
// webpack.config.js
module.exports = {
entry: {
page1: "./page1",
page2: "./page2"
},
output: {
filename: "[name].bundle.js",
chunkFilename: "[id].bundle.js"
}
......
}

一般可以直接通过require来加载对应的模块。

1
2
3
4
5
// page1.js
const a = require('./moduleA');
const b = require('./moduleB');

......

以angular为主的结构则需要在入口文件里定义module,然后通过require来装载其他模块。因为angular自带了一套依赖注入机制,但又没有依赖加载机制,所以webpack充当了它的加载模块机制。这样一来,当缺少模块时angular会直接抛出异常,而不会等到用到模块才会报错。

1
2
3
4
5
6
// page2.js
var ngModule = angular.module('xxx',[ ...])

require('./controller1')(ngModule)

ngModule.factory('FontFaceOnload', ['$window', $window=> $window.FontFaceOnload]);