Webpack+Vue+ES6 前端组件化开发mobile-multi-page应用实战总结和踩坑
本文版权归博客园和作者吴双本人共同所有 转载和爬虫请注明原文地址 www.cnblogs.com/tdws
一.写在前面
项目上线有一段时间了,一个基于webpack+vue+ES6的手机端多页面应用。其实说是多页面应用,实际上在webpack中属于四个app, 如果真是做纯单页面,那应该有二三十个页面吧。所以我这里的多页面应用,是分为四个SPA。比如微信最下面,有四个导航,微信,通讯录,发现,我。 那么这四个导航,就是我的四个SPA,配置多个入口即可。
在这里就不说太多代码了,项目结构将会放到github上,地址在后面给出,以供参考,上传的大概只是一个目录加上配置情况,其实关键点也就在webpack.config.js了,这里主要配置了entry,loader,plugins,output目录啥的。
在这里先附上package.json和webpack.config.js吧:
{
"name": "my-web",
"version": "1.0.0",
"description": "desc",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "webpack-dev-server --inline --hot",
"dev1": "webpack-dev-server --open",
"dev": "webpack-dev-server --inline --hot",
"build": "set NODE_ENV=production&&webpack"
},
"author": "ws",
"license": "ISC",
"devDependencies": {
"babel-core": "^6.24.1",
"babel-loader": "^7.0.0",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-preset-es2015": "^6.24.1",
"babel-runtime": "^6.23.0",
"css-loader": "^0.28.4",
"extract-text-webpack-plugin": "^2.1.0",
"glob": "^7.1.2",
"html-webpack-plugin": "^2.28.0",
"jquery": "^3.2.1",
"node-sass": "^4.5.3",
"sass-loader": "^6.0.5",
"slideout": "^1.0.1",
"style-loader": "^0.18.2",
"url-loader": "^0.5.8",
"vue": "^2.3.3",
"vue-croppa": "^0.1.0",
"vue-hot-reload-api": "^2.1.0",
"vue-html-loader": "^1.2.4",
"vue-ios-alertview": "^1.1.1",
"vue-loader": "^12.2.1",
"vue-resource": "^1.3.3",
"vue-router": "^2.7.0",
"vue-style-loader": "^3.0.1",
"vue-template-compiler": "^2.3.3",
"vue-touch": "^2.0.0-beta.4",
"webpack": "^2.6.1",
"webpack-dev-server": "^2.4.5"
}
}
var path = require('path');
var webpack = require('webpack');
// 将样式提取到单独的 css 文件中,而不是打包到 js 文件或使用 style 标签插入在 head 标签中
var ExtractTextPlugin = require('extract-text-webpack-plugin');
// 生成自动引用 js 文件的HTML
var HtmlWebpackPlugin = require('html-webpack-plugin');
var glob = require('glob'); var entries = getEntry('./source/**/*.js'); // 获得入口 js 文件
var chunks = Object.keys(entries);
console.log('输出chunks', chunks);
module.exports = {
entry: entries,
output: {
path: path.resolve(__dirname, 'public'), // html, css, js 图片等资源文件的输出路径,将所有资源文件放在 Public 目录
publicPath: '/public/', // html, css, js 图片等资源文件的 server 上的路径
filename: 'js/[name].js', // 每个入口 js 文件的生成配置
chunkFilename: 'js/[id].[hash].js'
},
externals: {
jquery: "$",
EXIF: "EXIF",
wx: "wx"
},
resolve: {
extensions: ['.js', '.vue'],
alias: {
'vue': __dirname + '/lib/vue/vue.js',
//'vue-alert': __dirname + '/lib/vue-alert/vue-alert.js'
},
}, module: {
loaders: [
{
test: /\.css$/,
// 使用提取 css 文件的插件,能帮我们提取 webpack 中引用的和 vue 组件中使用的样式
//loader: "style-loader!css-loader",
loader: ExtractTextPlugin.extract({ fallback: 'style-loader', use: 'css-loader' })
},
{
// vue-loader,加载 vue 组件
test: /\.vue$/,
loader: 'vue-loader',
options: {
//解析.vue文件中样式表
loaders: {
// Since sass-loader (weirdly) has SCSS as its default parse mode, we map
// the "scss" and "sass" values for the lang attribute to the right configs here.
// other preprocessors should work out of the box, no loader config like this necessary.
//'scss': 'vue-style-loader!css-loader!sass-loader',
//'css': 'vue-style-loader!css-loader!sass-loader',
//'js': 'babel-loader',
//'sass': 'vue-style-loader!css-loader!sass-loader?indentedSyntax'
css: ExtractTextPlugin.extract({ fallback: 'vue-style-loader', use: 'css-loader' }),
//exclude: [
// path.resolve(__dirname, ""),
// //path.resolve(__dirname, "app/test")
//]
//exclude:'/source/course/course-detail/course-detail.css'
}
// other vue-loader options go here
}
},
{
test: /\.js$/,
// 使用 es6 开发,这个加载器帮我们处理
loader: 'babel-loader',
exclude: /node_modules/
},
{
test: /\.(png|jpg|gif|svg)$/,
// 图片加载器,较小的图片转成 base64
loader: 'url-loader',
query: {
limit: 10000,
name: './imgs/[name].[ext]?[hash:7]'
}
}
]
},
plugins: [
// 提取公共模块
new webpack.optimize.CommonsChunkPlugin({
name: 'vendors', // 公共模块的名称
chunks: chunks, // chunks 是需要提取的模块
minChunks: chunks.length
}),
// 配置提取出的样式文件
new ExtractTextPlugin('css/[name].css')
]
}; var prod = process.env.NODE_ENV === 'production';
module.exports.plugins = (module.exports.plugins || []);
if (prod) {
module.exports.devtool = 'source-map';
module.exports.plugins = module.exports.plugins.concat([
// 借鉴 vue 官方的生成环境配置
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: '"production"'
}
}),
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
}
})
]);
} else {
module.exports.devtool = 'eval-source-map';
module.exports.output.publicPath = '/view/';
} var pages = getEntry('./source/**/*.html');
for (var pathname in pages) {
// 配置生成的 html 文件,定义路径等
var conf = {
filename: prod ? '../views/' + pathname + '.html' : pathname + '.html', // html 文件输出路径
template: pages[pathname], // 模板路径
inject: true, // js 插入位置
minify: {
removeComments: true,
collapseWhitespace: false
},
hash:true
};
if (pathname in module.exports.entry) {
conf.chunks = ['vendors', pathname];
//conf.hash = false;
}
// 需要生成几个 html 文件,就配置几个 HtmlWebpackPlugin 对象
module.exports.plugins.push(new HtmlWebpackPlugin(conf));
} // 根据项目具体需求,输出正确的 js 和 html 路径
function getEntry(globPath) {
var entries = {},
basename, tmp, pathname; glob.sync(globPath).forEach(function (entry) {
basename = path.basename(entry, path.extname(entry));
tmp = entry.split('/').splice(-3);
pathname = tmp.splice(0, 1) + '/' + basename; // 正确输出 js 和 html 的路径
entries[pathname] = entry;
});
console.log(entries);
return entries;
}
开发工具使用的VS2017,本来使用WS,但是用习惯VS的我还是受不了,毕竟17还是太强大了嘛。既然是vue项目,那数据请求肯定就是vue-res, 路由就是vue-loader,编译es6大家都是babel。 下面是项目结构预览:
他们分别是图片资源,引用库资源,发布打包后的js和css,src源码和打包后的html
二.几点重要的收获
1.组件化开发爽啊, 调用者只需要关注输入和输出,代码明朗,容易维护
2.vue-res promise异步风格太优美,太喜欢了。但是有坑,ios8.x,使用内核浏览器运行js, 不支持promise语法,所以需要在入口中,import几个npm下载的node module:

3.记得以前做一个手机端项目,完全没有自动化,各个页面间跳转慢的一比,一点也不流畅,项目结构不容易管理,重复代码特别多。
近百个页面js版本得不到控制,管理js,css引用困难。微信静态资源缓存如此严重,没有版本控制,每个页面js版本的修改要人命。
4.解决缓存问题,应禁止html缓存,由于使用extract-text-webpack-plugin,可以保证你html入口中只有简单的几行代码,等着自动化帮你引入所需js,所以即使禁止html缓存,也不会影响响应速度,毕竟我们的html文件 也就1-2k左右.html禁止缓存的原因是防止,js更新后,js hash版本已改变,但浏览器缓存的html中,依然是请求旧版本js文件,这样一来js版本控制变得没有意义。
5. js调用手机拍照, 调用安卓手机拍照不容易呀,所以如果只想在微信上使用网页的话,建议使用 微信js SDK。
6. 苹果手机和个别安卓手机,使用原生input调用拍照后,图片到页面中会出现旋转问题,所以在微信上 使用js sdk, 在其他浏览器上,就用EXIF.js 手动将其旋转90度 或者180度进行矫正。
7.推荐一款mobile用的不错的弹窗组件 vue-ios-alert. ios风格的弹窗。地址以及github: http://isay.me/vue-ios-alertview/example/
8.手机上的 日期 时分秒选择器,推荐一个有坑的货 https://github.com/k186 有坑哦,使用的话,请看closed的第一个issue。另外日期选择还是比较推荐原生。加上时分秒的话原生的可能就不好用。
9.页面touch切换tag 使用的一个vue-tab github找一找,ios8不支持 flex-shrink,要使用-webkit-flex-shrink。
10. 上拉加载更多 用的vue-loadmore,侧方滑动菜单 使用了jquery的slideout
11. 如果路由比较多的话,建议路由单独分一个js配置,并且一定要按需加载,否则打包文件太大。如果是用户点击率极高的路由,可以直接require进去。
12.一些js库,就不要通过require了,直接在html引入进去算了,毕竟这些库基本不会更改,也没必要控制版本
13.前端AOP, vue-res的拦截器点个赞,我可以在拦截器中,为我每一个请求 都加上authentication header等信息,像用jq的时候,我不得不手动把ajax包装一层
14.像有些数据的加载,文字方面,最好预先给出加载中这种提示,不能给空白。列表的加载 要多考虑加载中,加载完成和暂无数据的处理。见过很多app和网页都是进入到列表页,首先一个暂无数据的背景图给出来 了,结果稍等一下,数据又加载出来了....
15.虽然已经组件化了,但我还建议有一个每个页面公用需要require的js,我一般都叫application.js 在这里 可以放一些你的常量,枚举,公共方法,helpers,utils,ajax 等配置,并且在这里可以import footer header vue-res vue-alert 等一些每个组件或者页面都需要以来的组件
16.热替换是必须的,比以前用gulp livereload方便
17.手机端页面调试,推荐vConsole(去github找)。 示例:
18.经过babel编译es5的都没问题.。 我有个单独的小功能,没用es6,直接谷歌调试开发,结果到了ios9.x上 不支持也不报错,以后避免踩进去吧。下面是代码:
19. IOS上计算时间 需要new Date('2017/09/09')的格式, 而不能使用横杠的格式
三.一些缺点
1.脑子抽风啊,分为四个SPA, 整套项目下来,感觉还是应该做一个SPA。毕竟SPA之间切换,一个SPA切换到另一个SPA 还是加载东西太多,不够流畅。虽然微信浏览器缓存“严重”
2.项目结构划分还是不够合理,但感觉也还能对付用。
3.组件化没有发挥到极致,自己vue组件间通信没搞好,md找子组件,我竟然还有通过遍历的方式。
4.有些组件用的jquery的,搭配的不是很流畅,导致个别操作强行使用dom操作。
5.我有四个环境,开发,测试,demo, 线上。 每次发布到一个环境 都需要改了配置后,重新打包,很痛苦啊,关于这一点有什么好的办法吗?
四.写在最后
这个项目产品将继续开发,不过下一阶段还有个项目,我将使用一个SPA完成,关于vue有什么好的各种mobile组件,希望dalao不吝推荐。
如果,您认为阅读这篇博客让您有些收获,不妨点击一下右下加【推荐】按钮。
如果,您希望更容易地发现我的新博客,不妨点击下方红色【关注】的。
因为,我的分享热情也离不开您的肯定支持。
感谢您的阅读,我将持续输出分享,我是蜗牛, 保持学习,谨记谦虚。不端不装,有趣有梦。
Webpack+Vue+ES6 前端组件化开发mobile-multi-page应用实战总结和踩坑的更多相关文章
- Webpack+Vue+ES6 前端组件化开发mobile-multi-page应用实战总结
本文版权归博客园和作者吴双本人共同所有 转载和爬虫请注明原文地址 www.cnblogs.com/tdws 一.写在前面 项目上线有一段时间了,一个基于webpack+vue+ES6的手机端多页面应用 ...
- Vue 入门之组件化开发
Vue 入门之组件化开发 组件其实就是一个拥有样式.动画.js 逻辑.HTML 结构的综合块.前端组件化确实让大的前端团队更高效的开发前端项目.而作为前端比较流行的框架之一,Vue 的组件和也做的非常 ...
- AppBoxFuture(六): 前端组件化开发
前面几篇都是在介绍结构化与非结构化的数据存储,本篇换换口味介绍一下框架是如何实现前端组件化开发的.首先得感谢Vue.ElementUI等优秀的前端开源项目,这些项目帮助作者快速实现了框架的两个前端 ...
- vue.js原生组件化开发(一)——组件开发基础
前言 vue作为一个轻量级前端框架,其核心就是组件化开发.我们一般常用的是用脚手架vue-cli来进行开发和管理,一个个组件即为一个个vue页面,这种叫单文件组件.我们在引用组件之时只需将组件页面引入 ...
- 前端笔记之JavaScript面向对象(四)组件化开发&轮播图|俄罗斯方块实战
一.组件化开发 1.1组件化概述 页面特效的制作,特别需要HTML.CSS有固定的布局,所以说现在越来越流行组件开发的模式,就是用JS写一个类,当你实例化这个类的时候,页面上的效果布局也能自动完成. ...
- vue.js原生组件化开发(二)——父子组件
前言 在了解父子组件之前应先掌握组件开发基础.在实际开发过程中,组件之间可以嵌套,也因此生成父子组件. 父子组件创建流程 1.构建父子组件 1.1 全局注册 (1)构建注册子组件 //构建子组件chi ...
- vue(9)—— 组件化开发 - webpack(3)
前面两个终于把webpack相关配置解析完了.现在终于进入vue的开发了 vue组件化开发预热 前期准备 创建如下项目: app.js: footer.js: main.js: webpack.con ...
- 如何通过 Vue+Webpack 来做通用的前端组件化架构设计
目录: 1. 架构选型 2. 架构目录介绍 3. 架构说明 4. 招聘消息 目前如果要说比较流行的前端架构哪家强,屈指可数:reactjs.angularjs.emberj ...
- vue(8)—— 组件化开发 - webpack(2)
webpack的常用loder和插件 loder和插件是什么,现在暂且不表,看到后面你就懂了 引入css问题 直接用link标签导入css 在前面的 vue(7)—— 组件化开发 — webpack( ...
随机推荐
- 转载 转载 转载 数组a[],a,&a之间的区别
通俗理解:内存就是公寓房间,指针就是房间的门牌号,数组就是连续的公寓房间,数组名就是这组连续房间的起始地址,也就是第一个房间的地址. 例如int a[5] a是数组名,也就是第一个房间号 & ...
- MDK错误 Error: L6218E: Undefined symbol SystemInit (referred from startup_stm32f10x_hd.o). 解决方法
此错误产生的位置在STM32工程所包含的汇编启动代码文件,如下图 熟悉ARM汇编的朋友一定可以看出,这是一个子程序调用语句,而调用的子程序正是SystemInit.出现错误的原因就是汇编器没有在代码之 ...
- Java基础知识总结--反射
反射:在程序运行期间,Java运行时系统始终为所有的对象维护一个被称为运行时的类型标识.这个信息跟踪着每一个对象所属的类.虚拟机利用运行时类型信息选择相应的方法执行. Java反射机制是在系统运行状态 ...
- Oracle CPU使用率过高问题处理
1.下载Process Explorer 2.打开Process Explorer,查看CPU使用情况最高的进程 3.双击该进程,查看详情 \ 4. 获取cpu使用最好的线程tid 5. ...
- 小甲鱼Python第三讲课后习题
0.以下哪个变量的命名不正确?为什么? A:MM_520 B:_MM520_ C:520_MM D:_520MM 变量 命名:以字母.下划线.数字组成,以字母.下划线开头 1.除了使用反斜杠(\)进行 ...
- 【转】Java基础:System.out.println与System.err.println的区别
同时使用了System.out.println与System.err.println()打印输入内容,结果看到的内容和预想的不一样,顺序与预料的不同并不是因为err和out的区别导致,而是因为他们是两 ...
- CSS 埋点统计
原文地址: https://my.oschina.net/u/1778933/blog/1608904 CSS 埋点统计 当一个网站或者 App 的规模达到一定程度,需要分析用户在 App 或者网站的 ...
- .Net转Java.01.从Main(main)函数说起
在C#中,main函数的签名可以有四种 static void Main(string[] args)static void Main()static int Main(string[] args)s ...
- Jetpack 迁移到 androidX support MD
Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...
- ViewPager Fragment 懒加载 可见 总结 MD
Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...