记一次用vue2开发多页面应用

一.前提

  • 项目中有几个页面交互比较多,使用jquery方式实现,交互完成后,需要手动状态修改完成后,比较麻烦。选择使用mvvm模式的vue框架,以数据驱动可以加快开发效率。
  • 在此之前,使用vue写过spa应用,且使用官方vue-cli一键完成配置,对webpack不了解,这次尝试自己搭建脚手架。

二.实现

1.webpack配置

webpack的plugin具有很强大的功能,也是webpack相对于其他前端编译grunt,glup具备的优势。可以通过webpack plugin实现热替换,代码压缩混淆,代码分离等工作,帮助我们更好的进行前端开发及优化。

  • webpack plugin配置dev与production

在开发流程中,一般需要区分开发环境与生产环境。在开发环境中,进行本地调试开发,在生产环境编译打包文件。
以下,新建webpack.config.dev.js,与webpack.config.js文件分别作为开发环境与生产环境,在dev环境下实现热替换,在prod环境下实现多多页面输出。

使用DefinePlugin区分定义环境

在webpack.config.dev.js的plugin中添加

1
2
3
4
5
6
plugins: [
new webpack.DefinePlugin({
'process.env.NODE_ENV': '"dev"'
}),
...
]

在webpack.config.dev.js的plugin中添加

1
2
3
4
5
6
plugins: [
new webpack.DefinePlugin({
'process.env.NODE_ENV': '"production"'
}),
...
]

在package.json中添加钩子脚本

1
2
3
4
"scripts": {
"dev": "webpack-dev-server --config webpack.config.dev.js",
"build": "webpack --config webpack.config.js"
},
  • 多页面配置

在vue的spa应用中,单一入口,单一输出,webpack.config.js:

1
2
3
4
5
6
7
8
9
module.exports = {
entry: ['./src/main.js'], //编译入口文件
output: {
publicPath: config.publicPath, //服务器的路径
path: path.resolve(__dirname + config.publicPath), //编译到指定目录下
filename: '[name].js?v=[hash]' //编译后的文件名
},
...
}

在多页面应用中,设置多入口,多出口,webpack.config.js:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
var glob = require('glob');
var path = require('path');
var publicPath = "/dist/";
var entries = getEntry(['./src/views/*.js', './src/views/**/*.js']); // 获得入口js文件
module.exports = {
entry: entries,
output: {
path: __dirname + publicPath,
publicPath: publicPath,
filename: "[name].js",
libraryTarget: 'umd'
},
...
}
// 输出路径方法
function getEntry(globPath) {
var entries = {},
basename, tmp, pathname;
if (typeof (globPath) != "object") {
globPath = [globPath]
}
globPath.forEach((itemPath) => {
glob.sync(itemPath).forEach(function (entry) {
basename = path.basename(entry, path.extname(entry));
if (entry.split('/').length > 4) {
tmp = entry.split('/').splice(-3);
pathname = tmp.splice(0, 1) + '/' + basename; // 正确输出js和html的路径
entries[pathname] = entry;
} else {
entries[basename] = entry;
}
});
});
// entries['vendor'] = ['vue'];
return entries;
}
  • hot loaded配置

添加依赖

1
npm install webpack-dev-server --save-dev

webpack-dev-server实现了一个轻量的node.js express服务器,webpack.config.dev.js配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
module.exports = {
devtool: "#eval-source-map",
devServer: {
contentBase: "./src/public/",
colors: true,
historyApiFallback: true,
inline: true,
noInfo: true
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin()
]
...
}

其中contentBase属性为node服务指定的目录,访问本地资源及页面。

2.项目结构

目录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
.
├── README.md
├── dist // 输出文件夹
│   ├── vendors.bundle.js // 分离后的通用js
│   └── views // 页面输出后的js文件
├── node_modules // 依赖库
├── package.json
├── src // 项目主要模块
│   ├── common // 通用js,ajax请求,及全局Vue插件
│   ├── components // vue components
│   ├── public // 资源文件及html模板
│   └── views // 主要模块
│   ├── cart // 购物车模块
│   ├── cart.js // vue的初始化
│    └── cart.vue
...
├── stats.json
├── webpack.config.dev.js // 测试环境
└── webpack.config.js // 生产环境

src/public

1
2
3
4
5
6
src/public/ // 作为本地服务器指定的contentBase入口,访问本地资源及页面模板
├── css
├── display // 本地调试的html模板
├── font
├── img
└── js

三.优化

利用webpack plugin对代码压缩,提取分离

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
plugins: [
...
new webpack.optimize.CommonsChunkPlugin('vendor', 'vendors.bundle.js'),
new webpack.optimize.UglifyJsPlugin({
mangle: {
except: ['$super', '$', 'exports', 'require']
//以上变量‘$super’, ‘$’, ‘exports’ or ‘require’,不会被混淆
},
compress: {
warnings: false
}
}),
]