概述
从客岁短时间内对现有体系的革新到现在稳固实行,已好几个月,这套流程满足了一样平常前端开辟的流程。因为之前项目组的模块化自身做的不是很好,基本算是推到一半重来,虽然阵痛,但回忆起来确切异常值得。webpack,简朴来讲就是前端静态资本的打包东西,确切好用,道理也很简朴,比以AMD、CMD为范例的模块加载器好用多了,难怪玉伯说要给seajs、requirejs立一块墓碑了。在讲webpack这之前简朴说下前端模块化进程。
模块化1.0
// a.js
(function(){
// todo a
})();
// b.js
(function(){
// todo b
})();
// index.html
<script src="a.js"></script>
<script src="b.js"></script>
以上是在CommonJS范例出来之前的编码体式格局,人人应当异常熟习。别的另有经由过程定名空间的体式格局来举行模块化,实在也没有真正的处置惩罚题目。
模块化2.0
// a.js
define(function(require, exports, module){
// todo a
})
// b.js
define(function(require, exports, module){
var a = require('./a');
// todo b
})
// index.html
<script src="sea.js"></script>
<script>
sea.use(['b.js'], function(b){
// todo
});
</script>
这就是过去几年人人都异常熟习的模块化体式格局,在宣布上线时经由过程构建东西,提取模块id、以及模块的依靠,兼并紧缩代码等等构建事情。
然则用requirejs或许seajs,照样有些题目:
只能模块化加载js、css,而且还不帮你兼并,须要本身写插件去做兼并的逻辑,组件化并不简朴。
异步加载也不好用,尤其是布置时,hash后的资本途径自动替换还比较贫苦。
顺序照样要依靠seajs这个几kb的库,总觉得有点过剩。
模块化3.0
webpack出来后,文雅的处置惩罚了许多题目,而且简朴好用。它能把种种资本,比方JS(含JSX)、coffee、款式(含less/sass)、html、图片等静态资本都作为模块来处置惩罚。同时具有异步加载的才能,异常适用于大型庞杂的webapp的场景。webpack有以下特征:
兼容AMD/CMD的模块加载
js模块的写法遵照CommonJS范例
模块化一切静态资本(JS、CSS、html、图片、字体等)
开辟、布置便利,能替换大部份 grunt/gulp 的事情,比方打包、紧缩殽杂、图片转base64等
经由过程一个简朴的设置文件即可搞定这些。
实战
连系项目自身的特征,部份功用webpack没法做到,终究选用gulp+webpack体式格局来支撑前端的事情流,项目需求:
最小化设置项(webpack.config.js)
一切资本运用增量宣布战略,文件名悉数 md5 版本化
支撑多种模块化战略,运用 webpack 举行模块化打包
自动替换 html/js 内部资本援用途径,替换为 cdn/md5 版本化途径
轻松支撑 js资本内嵌到页面
开辟时监听文件,自动上传到开辟机
因为css是由重构同砚写,雪碧图,紧缩、宣布等等都由他们来做,所以没有斟酌加入到构建流程中来。
项目目次构造以下:
src/
js/
widget/
css/
img/
project_tpl/
gulpfile.js
app/
js/
css/
img/
index.html
tpl/
webpack.config.js
gulpfile.js
app/
src目次下是项目的源代码,每一个目次(app)即为一个项目,为了只管防止争执,一个人开辟并保护一个项面前目今的代码。
project_tpl为项目的模板,经由过程gulp新建项目,完成一些初始化设置,初始化后基本无需设置即可举行项目开辟。
js/css/img为站点的一些大众资本模块,widget为大众基本组件。
app项面前目今为营业的css、js、tpl目次,tpl为前端模板目次,能够经由过程webpack的html-loader插件加载。
gulpfile.js、webpack.config.js 为项目的构建东西设置文件。
如许一个项目的脚手架搭建完成,能够最先为项目添砖加瓦了。能够点击这里看github上的例子。
webpack设置文件
var webpack = require('webpack');
var globalConfig = require('../global.config');
var commonJSEntry = globalConfig.jsCommon;
var path = require('path');
module.exports = {
// 假如项目有多个HTML,或许多个进口
// 设置js进口文件,base是大众库设置,除了打包东西自动化抽取共用的模块,也能够自定义设置哪些模块为共用的。
entry:{
index: './js/index',
base: commonJSEntry,
},
// 文件产出目次
output:{
filename:'../test/js/[name].js',
// 异步加载的chunk,定名划定规矩,chunk我临时理解为从兼并的代码里分离出来的代码块,在处置惩罚非首屏逻辑,或许异步加载逻辑能够用这个。只要在js代码顶用require.ensure来异步加载模块即可。
chunkFilename: '../test/js/[chunkhash:8]_chunk.js',
// 资本文件的CDN前缀
publicPath: debug ? "" : '//cdn.xxx.com/webpack/test/'
},
resolve: {
// 模块的别号,一般能够为第三方模块
alias: {
ajax: "../../js/base/ajax",
dom: "../../js/base/dom"
},
// root模块的根途径,能够指定从哪里找模块,能够为数组[]
// 如许在模块依靠的时刻就不要写require(../../../xx.js)
// 直接为require(xx)
root: path.resolve('../../js')
},
// 模块加载器,加载差别范例的文件,须要下载或许开辟loader插件,以下为加载html模块的加载器
loader: [
{test: /\.html$/, loader: 'html'}
],
/*
1、能够经由过程设置文件指定哪位模块为大众模块,如许功用模块能够历久缓存。
诠释下这个插件的意义,就是提取大众的chunk,base对应了entry中的设置,"../test/js/common.js"是产出的途径,也就是将commonJSEntry中的设置模块兼并成一个common.js文件。
2、webpack也可自动提取页面之间公用的代码作为大众部份。下面的代码等于自动提取大众代码了。
var commonsPlugin = new webpack.optimize.CommonsChunkPlugin("../test/js/common.js");
*/
plugins: [
new webpack.optimize.CommonsChunkPlugin("base", "../test/js/common.js")
]
};
因为项目的特征,没有用到热插拔,所以就不举行讲解了。
gulp跑起来
webpack终究是当作gulp的一个插件来运转,读取的上述的webpack设置文件。
gulp.task('watch-html', function() {
// upload
});
gulp.task('watch-module', function() {
var watchPath = [
'../js/**',
'../css/**',
'../widget/**',
'js/**',
'css/**',
'tpl/**'
];
gulp.watch(watchPath, function(event){
gulp.src(watchPath)
.pipe(webpack(require('webpack.config')))
.pipe(gulp.dest(releaseRelativePath + projectName))
.pipe(upload(opt, function(err, data){})
})
});
gulp.task('default', ['watch-html', 'watch-module']);
// release build webpack module
gulp.task('release-module', function() {
var releasePath = [
'../js/**',
'../css/**',
'../widget/**',
'js/**',
'css/**',
'tpl/**'
];
return gulp.src(watchPath)
.pipe(webpack(require('webpack.config')))
.pipe(uglify())
.pipe(hash())
.pipe(rename(function(path) {
// 猎取当前的日期,将宣布文件已日期归类,更轻易查找文件
path.dirname = path.dirname + '/' + year + month + day;
})
.pipe(gulp.dest(releaseRelativePath + projectName))
.pipe(upload(opt, function(err, data){})
})
});
// release build html
gulp.task('release', ['release-module'], function(){
gulp.src(['**/*.html'])
.pipe(parseHtml(releaseRelativePath + projectName, CDN_URL))
.pipe(gulp.dest(releaseRelativePath + projectName))
.pipe(upload(opt, function(err, data){})
.pipe(uploadToCDN())
})
(以上用到的部份npm模块是自定义的)。
1、项目最先前,经由过程gulp init -p YourProjectName 来初始化项目
2、开辟和宣布两套敕令,开辟:gulp,宣布:gulp release
3、须要自行编写gulp插件来替换html中援用资本的途径,道理也很简朴,在构建webpack模块后,将产出的文件列表与原文件的映照关联保留在数组,查找html中援用的js途径,替换成hash后就能够了。
经由过程以上要领,就能够满足我们项目之前的需求,基本上做到自动化,自动构建,自动宣布剧本,html文件走内部宣布体系宣布。