作为从grunt、gulp一路走来的老码农,一开始用webpack的时候我是很抗拒的。但由于核心库使用了vue,而webpack又是vue的最佳拍档(vue作者专门为其写了vue-loader),所以用webpack来构建项目就成了自然而然的事情。经过一段时间的摸索,各个流程都跑通了,「从入门到放弃」的那点事也就都不算事了。

webpack是以模块为中心的打包工具,但由于其日渐丰富的插件,能做的事情已经很多了,从开发环境搭建到上线构建,几乎可以一条龙包办了。事实上我在最近的项目中,连gulp都省了,完全用webpack就完成了所有的工作。下面一一道来。

本地server

在前后端分离的大前提下,前端本地已不需要起后端服务了,那为什么还要起一个本地server呢?这个server主要提供以下支持:

  1. 静态资源访问

  2. 代码热更新(实时刷新浏览器)

  3. 模拟请求数据

  4. 代理http请求

本地server是由webpack插件webpack-dev-middleware提供的,它是基于express的,所以还需要把express也装上。配置代码相当简单:

var devMiddleware = require('webpack-dev-middleware')(compiler, {
publicPath: config.output.publicPath,
stats: {
colors: true,
chunks: false
}
}); app.use(devMiddleware);

通常我们把它保存为dev-server.js,然后配合npm script来启动这个server,在package.json中写好:

"scripts": {
"dev": "node ./build/dev-server.js"
}

然后一行命令就可以启动了:npm run dev

需要注意的一点事,当我们起了本地server之后,webpack打包后的文件并不写入到硬盘上,而是保存在内存中。所以你并不会在目录下看到生成的文件,但是浏览器已经能够按照路径进行访问了,这样开发环境下的编译速度就大大加快。

独立vue组件

用了webpack之后,写vue组件最爽的就是可以写成单独的.vue文件了,在一个文件中写好所有的样式、模板、js逻辑。然后vue-loader就会帮我们编译成标准的vue组件。

令人高兴的是,vue2.0引入了虚拟DOM来提高性能,vue-loader也会将我们的模板编译成虚拟DOM来使用,你也不必费劲再去写render函数了。

编译ES6

之前也说过项目已经完全用ES6了,所以我们在开发环境需要用babel进行编译,我们写ES6代码的地方有两个,一个是js文件,另一个是.vue文件中的。

js文件的在webpack配置文件中配置loader即可:

{
test: /\.js$/,
loader: 'babel',
exclude: /node_modules/
}

而.vue文件中的,vue-loader已经天然帮我们做了,所以不需要任何设置。

babel的配置项,写在.babelrc中放在根目录下即可。

编译sass

前端进入编译时代,css当然也是少不了的。项目中使用了sass来编写css代码,所以也需要在开发环境进行编译。需要编译的有两个地方,一个是外链的.scss文件,另一个是.vue文件中的。

对于.scss文件,我们还是用loader来处理,安装sass-loader,然后在webpack配置文件中配好:

{
test: /\.scss$/,
loader: ExtractTextPlugin.extract('style', 'css!sass')
}

至于.vue文件中的,vue-loader早帮我们做好了工作,只需在<style>标签加上lang属性就可以了,例如编译sass

<style lang="sass">
/*此处可以写sass代码啦*/ </style>

代码检查

在开发阶段进行代码检查也是一项必要工作,检查ES6当然eslint是标配,在配置文件中可以通过preLoaders来配置:

preLoaders: [
{
test: /\.(js|vue)$/,
exclude: /node_modules/,
loader: 'eslint-loader'
}
]

这样在js文件和.vue文件中的代码都会用eslint规则进行检查。eslint的配置同样写在.eslintrc文件中放在根目录下。

代码热更新

编译工作就是以上这些了。当我们开始正式敲代码之后,还有一个功能是梦寐以求的,那就是代码热更新。即编辑器保存代码后,浏览器实时刷新。这个特性在webpack中叫做”模块热替换(hot module repacement)“,使用webpack-hot-middleware这个插件来完成。

这个插件跟我们以前用的live-reload不同,它不会刷新浏览器页面,而是把模块进行热替换。这样的好处是,应用的当前状态还能保持,但是代码已经更新了。比以前爽了不止一点半点。

模拟数据

前后端分离开发中,还有重要的一环,就是前端mock数据。在后端接口开发完成之前,我们可以通过自己模拟的数据完成调试。

事实上mock数据并不需要webpack提供,而是通过我们的本地server,写express中间件的方式。需要以下两步:

第一步,根目录下建一个mock目录,用于放置假数据,每个接口一个js文件,为了便于express使用,文件的格式如下:

module.exports = {
api: '/api/mock/banner',
response: function (req, res) {
res.json({
success: true,
data: {
name: 'test'
}
});
}
}

第二步,在dev-server中把mock的数据挂载到express上,代码如下:

var mockDir = path.resolve(__dirname, '../mock');
fs.readdirSync(mockDir).forEach(function (file) {
var mock = require(path.resolve(mockDir, file));
app.use(mock.api, mock.response);
});

这样当我们请求的路径中含有/api/mock字样时,就会返回我们mock的数据啦。当后端的接口开发完成时,我们就可以把路径中的mock去掉,从而去请求后端的接口。

代理请求

由于我们起了本地server,ajax路径是相对的,所以请求会打到本地的这个server上。当我们需要调试后端接口时,就得把请求转发到后端服务器。为了避免跨域的麻烦,通常需要配置http代理。

我使用了http-proxy-middleware这个中间件,这也是和webpack无关的,它也是一个express中间件。配置方法如下:

app.use(proxy('/api', {
target: {
host: 'localhost',
protocol: 'http:',
port: 5050
},
logLevel: 'debug'
}));

我们和后端协商好,所有异步请求都带"/api"前缀,这样我就把请求转发到后端服务器了。此处我把host填了localhost,意味着我本地起了一个后端服务,事实上可以指向任何一台可以提供接口的服务器。

这个proxy中间件有一个小坑,就是路径必须向我这样分开写。如果拼在一起不会生效,我目前没找到原因。

移动端远程调试

出于平台兼容性的考虑,移动端调试我选择了weinre。用过weinre的同学应该知道,我们需要在页面上嵌一个<script>标签才能使用weinre。不熟悉的同学可以参考我之前写的这篇:http://www.cnblogs.com/lvdabao/p/3436620.html

所以,我们需要对当前运行的环境进行判断,如果是开发环境才嵌入这个标签。我用了一个叫做DefinePlugin的插件来在通过webpack在页面全局定义变量,用法如下:

new webpack.DefinePlugin({
LOCAL_IP: JSON.stringify(localIP),
__ENV__: JSON.stringify('dev'),
WEINRE_RUN: JSON.stringify(process.argv[2]=='weinre')
})

这样,在页面初始化的时候,我们就可以根据当前的环境来决定是否嵌入这个<script>啦,如下:

if(__ENV__ == 'dev' && WEINRE_RUN){
document.write('<script src="http://'+LOCAL_IP+':8080/target/target-script-min.js#anonymous"></script>');
}

插入<script>标签

我们的js打包好后,下一步就是把它引入到html文件了。由于我们通常会用md5作为文件名来控制js版本,所以html中的文件地址就需要每次构建后进行更新。

webpack中是通过HtmlWebpackPlugin这个插件来实现的,它的特点在于,每次构建基于一个html模板来生成新的html文件,所以并不是替换js路径。在webpack的plugins选项中如下配置:

new HtmlWebpackPlugin({
filename: path.resolve(__dirname, '../static/dist/index.html'),
chunks: ['vendor', 'components', 'app'],
template: path.resolve(__dirname, '../static/src/index.html'),
inject: true
})

代码压缩

在gulp时代,我们是通过配置gulp任务来完成js的压缩。在webpack中,是通过插件来完成的,相同的道理,在plugins中进行如下配置:

new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
}
})

另外,webpack可以进行sourcemap配置,用于帮助映射文件,开启代码如下:devtool: 'source-map'

打包结果分析

在打包完成之后,我们经常会有这个心理:生成的文件完全不可读,打包的结果到底对不对,有没有重复打包,有没有冗余的东西。

这个时候就需要一个分析工具了,webpack有这样一个插件,能以可视化的方式展示打包结果,为你提供分析需求。它就是BundleAnalyzerPlugin,相当好用,我上一张我的截图:

上线构建

以上大部分是开发环境需要的配置,当我们本地测试完毕需要上线时,就需要真正生成文件了。

我们一般会准备两个或者多个(如何有多个环境,如test环境)webpack配置文件,用于不同的环境。在线上服务器跑的配置文件我们一般会修改输出地址,如果需要配cdn的话,把output中的publicPath填成cdn地址即可。然后直接运行webpack编译命令,而不是像本地server那样起。

同样我们也会写一个npm script,像这样:

"scripts": {
"dev": "node ./build/dev-server.js",
"build": "webpack --config ./build/prod.webpack.config.js"
}

我对webpack的应用大概就是这么多了,本想大致介绍,没想到一贴就是这么多代码~~其实webpack的精髓我本篇并未提及,那就是打包策略的选择,不同的项目架构需要不同的打包方式,而这个过程,则充满了挑战,你懂的。

(本文始发于我的微信公众号(doctor-programmer),整理重新编辑后发于博客,有兴趣的同学欢迎关注我的公众号,右边扫码去吧~)

webpack搭建前端一条龙服务的更多相关文章

  1. [坑况]——webpack搭建前端环境踩过的坑啊

    前言 嘿哈,webpack搭建前端环境踩过的坑啊! 第一个:完全不知所措 webpack4 下面用不了HtmlWebpackPlugin 和 ExtractTextPlugin 解决方案: html- ...

  2. 快速搞定用Vue+Webpack搭建前端项目(学习好久了,该写点东西了......)

    现在开始安装环境 一.安装node.js 首先要安装node.js,去nodejs官网下载即可,地址:http://nodejs.cn/中文网. 安装完成后,打开终端(windows键+R)搜索cmd ...

  3. webpack搭建前端开发环境

    webpack的版本已经是来到了4.0,口号是无配置就可以使用webpack,当然是使用一些基本的功能 1.安装以下webpack的一些必须npm包 npm install webpack npm i ...

  4. webpack搭建vue项目开发环境【文档向学习】

    为何有这篇文章 各个社区已经有无数篇帖子介绍如何使用webpack搭建前端项目,但无论是出于学习webpack的目的还是为了解决工作实际需要都面临着一个现实问题,那就是版本更新.别人的帖子可能刚写好版 ...

  5. webpack 4.x之搭建前端开发环境

    webpack是一个现代JavaScript应用程序的静态模块打包器,借用官网的一张图,它能够将一些预处理语言,js的最新语法转换成浏览器识别的内容.现在一般的前端框架都有比较成熟的脚手架,大多数对w ...

  6. 26、前端知识点--利用webpack搭建脚手架一套完整流程

    前言 我们的目标是利用webpack搭建一个基于react + react-router +dva + es6 + less + antd用于中后台开发的脚手架,同学们可能会说社区里那么多优秀的脚手架 ...

  7. 前端微服务-面向web平台级应用的设计

    从去年开始,前端领域就出现了一个‘微应用’的名词,说的是前端架构的一种设计思路,业内都把它和后端的微服务进行类比,当时忙于公司的项目.没有静下心来好好了解,现在项目结束,再加上最近看的几篇关于前端微服 ...

  8. 使用AWS亚马逊云搭建Gmail转发服务(三)

    title: 使用AWS亚马逊云搭建Gmail转发服务(三) author:青南 date: 2015-01-02 15:42:22 categories: [Python] tags: [log,G ...

  9. Asp.Net Core 项目实战之权限管理系统(1) 使用AdminLTE搭建前端

    0 Asp.Net Core 项目实战之权限管理系统(0) 无中生有 1 Asp.Net Core 项目实战之权限管理系统(1) 使用AdminLTE搭建前端 2 Asp.Net Core 项目实战之 ...

随机推荐

  1. 通过adb方式给安卓手机截图的cmd批处理文件

    @echo off rem  通过adb方式截图rem  需要安装adb ,一般安装了android sdk 默认带了adb ,路径为sdk目录的android-sdk\platform-toolsr ...

  2. AFNetworking 3.0 源码解读 总结(干货)(下)

    承接上一篇AFNetworking 3.0 源码解读 总结(干货)(上) 21.网络服务类型NSURLRequestNetworkServiceType 示例代码: typedef NS_ENUM(N ...

  3. 【基于WinForm+Access局域网共享数据库的项目总结】之篇一:WinForm开发总体概述与技术实现

    篇一:WinForm开发总体概述与技术实现 篇二:WinForm开发扇形图统计和Excel数据导出 篇三:Access远程连接数据库和窗体打包部署 [小记]:最近基于WinForm+Access数据库 ...

  4. .Net语言 APP开发平台——Smobiler学习日志:手机应用的TextTabBar快速实现方式

    参考页面: http://www.yuanjiaocheng.net/webapi/create-crud-api-1-put.html http://www.yuanjiaocheng.net/we ...

  5. AutoMapper的介绍与使用(一)

    软件环境 vs2015 asp.net mvc 5 .NET Framework 4.5.2 AutoMapper 5.2.0.0 AutoMapper安装 新建asp.net mvc 项目 Auto ...

  6. spider RPC入门指南

    本部分将介绍使用spider RPC开发分布式应用的客户端和服务端. spider RPC中间件基于J2SE 8开发,因此需要确保服务器上安装了JDK 8及以上版本,不依赖于任何额外需要独立安装和配置 ...

  7. Android——eclipse下运行android项目报错 Conversion to Dalvik format failed with error 1解决

    在eclipse中导入android项目,项目正常没有任何错误,但是运行时候会报错,(clean什么的都没用了.....)如图: 百度大神大多说是jdk的问题,解决: 右键项目-Properties如 ...

  8. git和pycharm管理代码

    首先明白三个概念,服务器代码库,本地代码库,和正在coding的项目. coding完毕后,先通过commit提交到本地代码库,然后通过push再提交server的代码库    git步骤 git c ...

  9. IIS启动失败,启动Windows Process Activation Service时,出现错误13:数据无效 ;HTTP 错误 401.2 - Unauthorized 由于身份验证头无效,您无权查看此页

    因为修改过管理员账号的密码后重启服务器导致IIS无法启动,出现已下异常 1.解决:"启动Windows Process Activation Service时,出现错误13:数据无效&quo ...

  10. Linux测试环境搭建的学习建议

    随着Linux应用的扩展许多朋友开始接触Linux,根据学习Windwos的经验往往有一些茫然的感觉:不知从何处开始学起.这里介绍学习Linux测试环境搭建的一些建议. 一.Linux测试环境搭建从基 ...