随着年初开始使用webpack重构公司的广告代码,已经有将近一年的时间了,需求也渐渐的稳定了。我想也是时候将这几个工程整理一下,顺带着处理一些历史问题。

  由于当年各个业务线没有整合、需求也没有固定,考虑到将来随着不同业务线的发展方向不同,我为不同业务线的广告代码创立了不同的git工程,分别开发。但是我仍然为他们采用了相同的项目配置和基础逻辑,为将来有一天需要整合的时候做准备。这就导致了在不同业务线的广告代码中我有很多相同的基础模块,一旦修改这些模块,就要分别手动同步一遍,费时费力。因此这一次的优化的第一要务就是合并工程。另外采用webpack开发,我日后加入es6模块后需要source-map来方便调试。最后就是进来使用vue-cli的感悟,我原有的工程太依赖gulp,在阅读了vue-cli生成的webpack工程后,我打算尝试将项目中的gulp替换成npm script。

  因此我这次优化的任务就有了以下的几条:

  1、工程合并:webpack多入口;

  2、soucemap:加入sourcemap选项,并区分开发联调环境和上线环境;

  3、npm script替换gulp;

  4、bug修改;

一、工程合并、多入口

  最开始的时候将pc和wap的广告代码分别配置了两个git仓库,由于业务模式是差不多的,所以才用了相似的架构,不同点在于两端的广告特型是不同的、浏览器适配方案不同,这就导致了两份代码中有大量的相同的模块,每次修改这些相同的模块时要同事修改另一个,当是的做法是将这些模块猎在一个json文件中,一旦有修改就跑一段gulp脚本同步一下。但是这样做终究不是办法。这本身就是一个很不合理的方案,那么我为什么要分成两个。原因是长期以来PC的后台和wap的后台长期由两个不同的后端组编写,而且后端架构分别由PHP和Java实现,不同业务线的维护工作有可能拆分到别的部门来维护,这是一个历史原因。正是基于这个原因,我没有将两个藕合在一起,以方有一天我需要将两份代码拆开交给不同的团队来维护。

  但是我仍然考虑了有一天会合并在一起,所以一直强行规范这两个项目中逻辑结构和相同的功能模块保持同步,这为我能够在未来的某一天可以顺利的将两个工程合并以及当出现新业务线时,可以快速编译出一份新的广告代码,我的代码一定要能支持不同的场景,并不为了某一个业务线而产生。事实上随着广告业务资源的整合与稳定,我现在打算做出这种尝试。

  我在最初选用webpack也是出于多入口,理论上我只需要将wap中不同的入口模块和业务特型拷贝到PC,然后修改webpack配置文件,就可以实现合并。

那么我简单说一下webpack的多入口配置(我先给出官方文档):

  我们要关注的主要是webpack.config.js,当然你的工程中webpack配置文件可能不叫这个名字。以我的为例:

 var path = require('path');
var webpack = require('webpack');
//var HtmlwebpackPlugin = require('html-webpack-plugin');
//定义了一些文件夹的路径
var ROOT_PATH = path.resolve(__dirname);
var APP_PATH = path.resolve(ROOT_PATH, './src/app');
var BUILD_PATH = path.resolve(ROOT_PATH, './src/build');
// var NODE_PATH = path.resolve(__dirname, 'node_modules'); module.exports = {
//项目的文件夹 可以直接用文件夹名称 默认会找index.js 也可以确定是哪个文件名字
entry: {
"yourcodepcv1": APP_PATH + '/index.js',
"yourcodewapv1": APP_PATH + '/index-wap.js'
},
//输出的文件名 合并以后的js会命名为adsfehomev1.js
output: {
path: BUILD_PATH,
filename: '[name].js'//,
// sourceMapFilename: '[file].map',
// devtoolLineToLine: true
},
devtool: '#source-map',
externals:{
jquery: "jQuery"
}
};

  其实,很简单。我们一起来看一下,主要看module.exports中的entry和output,entry接收我们传入一个对象如下图,每一组的键值对都是一个入口,我这里写了两个入口文件。

  但是webpack并不允许我们传入一个好几组输出键值对。事实上入口中的每一个键值对在webpack中被视为一个“chunk”,我们在ouput中的[name]会被入口中的键名替换,可替换的不仅仅是键名,我们还可以加入[id]、[hash]、[chunkhash]等。

                

实际运行webpack后会看到终端中如下信息:

  其中有一列chunks,看到我们有两个chunk: 0和1。 0是我的pc代码,1是wap的。而对应的source-map也不会新建chunk。输出是也用了我们的[name]。

  实际开发中,当然不仅仅是入口不同,webpack通过require关键字查找文件,如果不同入口饮用了同一个模块,但是这个模块却依赖pc和wap各自的模块,我们可以在入口处定义好一个map缓存到一个通用的数据模块,这个模块的数据并不会硬编码,而是由入口处传入。也可以是各写各的,仅仅把复用的模块提出来饮用。但是这样做虽然简单但是当我想在加入一个入口时,就要写一溜文件,并不如入口定义map这种方便,加一个文件就行。当然方法有很多,条条大路通罗马,js语法是很强大的。

二、sourcemap

  这个其实比较简单,webpack是支持的,看我上面的配置文件,就可以看到 :

devtool: '#source-map' 

  看过我第一篇文章的朋友会看到,我最开始是用requireJS写的,好处在于开发时文件有浏览器异步加载,调试的时候找到那个文件就比较好调试。可是现在不同了我用webpack在nodeJS环境预编译打成一个文件。试想一下文件挺大的,而且和我写的并不是完全一样,找个东西不太方便,何况我用ES6写的部分更是被转化了。我需要souce-map来告诉我应该对应源文件的那一行。

三、npm script代替gulp

  我在开始写的时候直接用了gulp,不得不承认gulp很强大,而且很方便。可是我要做的事情并没有那么复杂,我需要的主要是:多任务、不用记不同的命令、webpack打包、mocha测试、jslint检查、开发环境变异、上线环境打包、部署等。其实不需要太深厚的nodejs功力,即使不实用gulp也可以搞定。

  其实我这种想法来自于我前段时间写vue,当时我用到了vue官方的vue-cli,对 就是那个脚手架里面虽然用了webpack,可是没有用gulp、grunt等工具。取而代替,用的是npm script。用过的同学会了解,就是package.json中那个“scripts”快捷命令。其实从另一个方面来说gulp和jQuery都是让人又爱又恨的工具,好的是确实方便,不好的是这些工具让我们对原生技术的原理、机制有了错误的理解。而且npm的包要比gulp的包要多很多,一般来说,功能都是在npm有了用着不错,想在gulp中用才会被人封装成gulp-XXX包。相应的更新维护速度,谁比较快就比较明显了。

  下面我就简单的以我的工程为例子介绍一下,如何使用npm script配置工程:

  就一我dev(开发环境,watch编译)和build(打包、压缩)为例:npm run dev;npm run build就可以调用。

  

  对于我来说开发环境只要在终端输入webpack就可以了。而我原来是怎么做的:为了让gulp能够控制整个流程,我是在gulp中require("webpack")而是利用gulp的watch,这么做的缺点在于为了用gulp无意中让webpack的使用更加繁琐,而且gulp的watch相当于gulp取监听文件变化,在取调用webpack,如果写的不好每次相当于从新运行webpack,ES5还好,如果用了很多loader,比如ES6 bable,就会很慢(10s以上,不能算是即时编译)。而webpack自带的 -w不同,第一次慢一点,之后就缓存在内存中了,即使是ES6,也会很快。

  问题来了,我build为什么不想dev那样写?因为build不仅仅用到了webpack,而且用了不同的webpack配置。我把要做的事情封装到minitodist.js中,并且因为build任务和cdn任务很像,我在调用npm run build的语句中传入了一个参数‘dist’。那么有什么不同呢:

  1、调取不同的webpack配置;

  2、修改版本变量;

  3、根据参数输出到不同文件夹;

  其实webpack配置仅仅是一部分不同,所以我用了webpack-merge来生成build用的配置:

  

 var path = require('path')
var webpack = require('webpack');
var merge = require('webpack-merge');
var baseWebpackConfig = require('./webpack.config');
var ROOT_PATH = path.resolve(__dirname);
var APP_PATH = path.resolve(ROOT_PATH, './src/app');
var BUILD_PATH = path.resolve(ROOT_PATH, './dist'); var modifiedDate = +(new Date()); var webpackConfig = merge(baseWebpackConfig, {
devtool: false,
output: {
path: BUILD_PATH,
filename: '[name].min.js',
},
plugins: [
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
}
}),
new webpack.BannerPlugin('This file is modified at:' + modifiedDate)
]
}); module.exports = webpackConfig

  先写var baseWebpackConfig = require('./webpack.config');来获取webpack.config.js。再调用webpack-merge模块创建新的配置,通过exports输出。

  比如我想要在线上环境使用已经压缩的代码。我就在新的配置中的“plugins”中加入webpack.optimize.UglifyJsPlugin,并且在输出时将文件名改成XXX.min.js(也可以不加min)。我也可以在文件头加入有关版本的注释(webpack.BannerPlugin)。

  关于node环境调用文件的参数的问题。当你用如下语句:

node xx.js ‘abc’

  在xx.js中可以这样拿到:(具体原理就不解释了)

var arguments = process.argv.splice(2);
console.log(arguments[0]);

  如package.json文件我陆续的写了别的任务。目前是不需要使用gulp的,对比一下我前后的依赖列表:

之前:之后:

  是不是感觉少了很多。

  总结:不管部门的调整后,我是否还会维护这套广告代码,我仍希望交给别人一套易读的容易维护的工程,我希望我写的不仅仅是程序,而是工程,有始有终。

我和我的广告前端代码(六):webpack工程合并、也许我不需要gulp的更多相关文章

  1. 我和我的广告前端代码(四):后台系统中,初尝vue、vue-cli

    有一段都在重构之前文章<我和我的广告前端代码(三):一次重来的机会,必要的技术选型>中提到的广告前台展示项目,原有的基于页面的请求,改成了单广告位请求在这个过程中经历了好几次架构变更以及项 ...

  2. 腾讯ISUX网页前端代码分析

    看了一下腾讯ISUX网页,无论是pc端还是移动端,展示都挺好看的,先对其代码进行分析如下: 1,先看前三行代码 <!DOCTYPE html> <!-- 腾讯 ISUX 是腾讯集团核 ...

  3. Effective前端5:减少前端代码耦合

    什么是代码耦合?代码耦合的表现是改了一点毛发而牵动了全身,或者是想要改点东西,需要在一堆代码里面找半天.由于前端需要组织js/css/html,耦合的问题可能会更加明显,下面按照耦合的情况分别说明: ...

  4. 【前端构建】WebPack实例与前端性能优化

    计划把微信的文章也搬一份上来. 这篇主要介绍一下我在玩Webpack过程中的心得.通过实例介绍WebPack的安装,插件使用及加载策略.感受构建工具给前端优化工作带来的便利. 壹 | Fisrt 曾几 ...

  5. 前端模块化工具-webpack

    详解前端模块化工具-webpack webpack是一个module bundler,抛开博大精深的汉字问题,我们暂且管他叫'模块管理工具'.随着js能做的事情越来越多,浏览器.服务器,js似乎无处不 ...

  6. Web 前端代码规范

    Web 前端代码规范 最后更新时间:2017-06-25 原始文章链接:https://github.com/bxm0927/web-code-standards 此项目用于记录规范的.高可维护性的前 ...

  7. app前端代码打包步骤

    一.搭建项目环境 1.安装node.js 在网上找到nodejs压缩包,下载解压后安装node-v8.9.3-x64.msi文件. 安装完毕后,在windows的cmd控制台输入node -v或nod ...

  8. 前端工程化与webpack

    (1) 前端工程化   近几年来,前端领域飞速发展,前端的工作早已不再是切几张图,写几个页面那么简单,项目比较大时,很可能会多人协同开发,模块化,组件化,CSS预编译等技术也被广泛的使用.前端自动化( ...

  9. 窥探原理:实现一个简单的前端代码打包器 Roid

    roid roid 是一个极其简单的打包软件,使用 node.js 开发而成,看完本文,你可以实现一个非常简单的,但是又有实际用途的前端代码打包工具. 如果不想看教程,直接看代码的(全部注释):点击地 ...

随机推荐

  1. STM32Cubemx出现工程突然自动退出的问题

    STM32Cubemx出现工程突然自动退出的问题 转载请注明出处,谢谢 https://www.cnblogs.com/kevin-nancy/p/10561944.html 或者 https://b ...

  2. 修改Android解锁界面

    解锁界面效果类似如下 其实这也是我后面做出的效果,样机因为没有ROOT不好调试截图,功能是将解锁的图标添加了最近运行的运用的图标,这样的话更方便用户去使用 1.分析 1.1.Android锁屏功能分析 ...

  3. Hashtable和HashMap的区别,Properties类的简单使用

    一.Java Properties类 Java中有个比较重要的类Properties(Java.util.Properties),主要用于读取Java的配置文件,各种语言都有自己所支持的配置文件,配置 ...

  4. 【一】JMeter的介绍安装和使用

    利用JMeter进行性能测试 一.JMeter介绍二.Jmeter安装三.工作原理四.脚本录制五.运行JMeter进行测试六.JMeter主要组件介绍七.参数化设置八.动态数据关联九.使用插件进行服务 ...

  5. 面试基础(二)-mem函数

    常考的函数有下面三个,memset,memcpy,memmove,一定要记住三个函数的函数原型,熟记返回值类型和参数类型,当然也不能忘记参数检查   memset #include<iostre ...

  6. Ruby(或cmd中)输入命令行编译sass

    Ruby(或cmd中)输入命令行编译sass步骤如下: 举例: 1.在F盘中新建一个总文件夹,比如test文件夹,其中在该文件夹下面建立html.images.js.sass等文件夹. 2.在sass ...

  7. 如何在web.config文件中配置Session变量的生命周期

    实例说明:在网上购物商城中,为了维护在线购物环境,一般只有注册会员才可以购买商品.实现购物功能时,先通过Session变量记录会员的登录名,然后在购买商品页面通过判断会员是否登录确定其能否购买商品. ...

  8. webstrom 在脚本区域写其他语言得到语法提示

    webstrom 在脚本区域写其他语言得到语法提示 webstrom 的提示小灯泡 点击inject language or reference 选择相应的语言. 如果写的内容比较多, 可以按照web ...

  9. 彻底解决INSTALL_FAILED_UPDATE_INCOMPATIBLE的安装错误

    利用adb shell进入系统,进入/data/app或者/data/data,删除跟你安装的apk同样的包名: 按Ctrl+C退出系统,利用adb pull /data/system/package ...

  10. 获取select下拉框的value以及文本内容

    select下拉框在项目开发中是经常用到的,特别是在联级菜单方面的应用更为广泛.但是,对于一些初学者来说,如何获取下拉框子节点option的value值和文本内容,还是有一点难度的.其他的就不说了,现 ...