├── .gitignore ├── template ├── page.js ├── src │ ├── common │ │ ├── icons │ │ │ ├── index.js │ │ │ └── face.js │ │ ├── style │ │ │ ├── common.scss │ │ │ └── svg.css │ │ ├── assets │ │ │ └── test.png │ │ ├── util │ │ │ └── message.js │ │ ├── components │ │ │ └── Dialog.vue │ │ └── svg │ │ │ └── face.svg │ └── view │ │ └── index │ │ ├── styles │ │ ├── index.css │ │ └── test.scss │ │ ├── assets │ │ └── turn-pointer.png │ │ ├── components │ │ ├── Shape.vue │ │ └── App.vue │ │ ├── main.js │ │ └── template.html ├── .babelrc ├── .gitignore ├── build │ ├── vue-loader.config.js │ ├── dev-client.js │ ├── config.js │ ├── server.js │ ├── webpack.dev.js │ ├── webpack.base.js │ ├── css-loaders.js │ ├── webpack.prod.js │ └── webpack.dll.js ├── gulpfile.js ├── README.md ├── package.json └── lib │ └── zepto.min.js ├── meta.json └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | -------------------------------------------------------------------------------- /template/page.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 需要构建的页面 一次只构建一个页面 3 | */ 4 | module.exports = 'index' -------------------------------------------------------------------------------- /template/src/common/icons/index.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | require('./face') 3 | -------------------------------------------------------------------------------- /template/src/common/style/common.scss: -------------------------------------------------------------------------------- 1 | .color { 2 | transform: rotate(45deg); 3 | display: flex; 4 | } -------------------------------------------------------------------------------- /template/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [["es2015", { "modules": false }], "stage-2"], 3 | "comments": false 4 | } 5 | -------------------------------------------------------------------------------- /template/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | npm-debug.log 4 | .idea 5 | manifest.json 6 | dist 7 | lib/vendor -------------------------------------------------------------------------------- /template/src/view/index/styles/index.css: -------------------------------------------------------------------------------- 1 | .header { 2 | color: red; 3 | transition: all .3s ease; 4 | display: flex; 5 | } -------------------------------------------------------------------------------- /template/src/common/assets/test.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agileago/webpack-mutiple/HEAD/template/src/common/assets/test.png -------------------------------------------------------------------------------- /template/src/view/index/assets/turn-pointer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agileago/webpack-mutiple/HEAD/template/src/view/index/assets/turn-pointer.png -------------------------------------------------------------------------------- /template/src/common/util/message.js: -------------------------------------------------------------------------------- 1 | export function show () { 2 | console.log('i am show') 3 | } 4 | 5 | export function bar () { 6 | console.log('i am bar') 7 | } -------------------------------------------------------------------------------- /template/build/vue-loader.config.js: -------------------------------------------------------------------------------- 1 | const page = require('./config') 2 | 3 | module.exports = { 4 | postcss: [require('autoprefixer')({ browsers: page.browsers })], 5 | loaders: { 6 | scss: 'vue-style-loader!css-loader!sass-loader' 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /template/build/dev-client.js: -------------------------------------------------------------------------------- 1 | require('eventsource-polyfill') 2 | var hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true') 3 | 4 | hotClient.subscribe(function (event) { 5 | if (event.action === 'reload') { 6 | window.location.reload() 7 | } 8 | }) -------------------------------------------------------------------------------- /template/src/view/index/styles/test.scss: -------------------------------------------------------------------------------- 1 | .header { 2 | animation: bling 2s ease both; 3 | 4 | @at-root { 5 | @keyframes bling { 6 | 0% { 7 | opacity: 0; 8 | color: red; 9 | } 10 | 100% { 11 | opacity: 1; 12 | color: green; 13 | } 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /template/gulpfile.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp') 2 | var revHash = require('gulp-rev-hash3') 3 | 4 | gulp.task('rev-hash', function () { 5 | return gulp.src(`dist/**/index.html`) 6 | .pipe(revHash({ 7 | assetsDir: 'dist', 8 | projectPath: './' 9 | })) 10 | .pipe(gulp.dest(`dist`)) 11 | }) 12 | 13 | gulp.task('default', ['rev-hash']) -------------------------------------------------------------------------------- /meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "schema": { 3 | "name": { 4 | "type": "string", 5 | "required": true, 6 | "label": "Project name" 7 | }, 8 | "description": { 9 | "type": "string", 10 | "required": false, 11 | "label": "Project description", 12 | "default": "A Vue.js project" 13 | }, 14 | "author": { 15 | "type": "string", 16 | "label": "Author" 17 | } 18 | }, 19 | "skipInterpolation": "src/**/*.vue" 20 | } 21 | -------------------------------------------------------------------------------- /template/src/common/style/svg.css: -------------------------------------------------------------------------------- 1 | .svg-icon { 2 | display: inline-block; 3 | width: 1em; 4 | height: 1em; 5 | color: inherit; 6 | vertical-align: middle; 7 | fill: none; 8 | stroke: currentColor; 9 | } 10 | 11 | .svg-fill { 12 | fill: currentColor; 13 | stroke: none; 14 | } 15 | 16 | .svg-up { 17 | transform: rotate(-90deg); 18 | } 19 | 20 | .svg-right { 21 | /*default*/ 22 | transform: rotate(0deg); 23 | } 24 | 25 | .svg-down { 26 | transform: rotate(90deg); 27 | } 28 | 29 | .svg-left { 30 | transform: rotate(180deg); 31 | } -------------------------------------------------------------------------------- /template/src/view/index/components/Shape.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 16 | 17 | -------------------------------------------------------------------------------- /template/src/view/index/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | require('es6-promise').polyfill() 3 | import 'weui' 4 | import App from './components/App.vue' 5 | import { ToastPlugin } from 'vux' 6 | import * as svgicon from 'vue-svgicon' 7 | import '../../common/style/svg.css' 8 | import '../../common/icons' 9 | 10 | Vue.use(svgicon, { 11 | tagname: 'svgicon', 12 | defaultWidth: '1.2em', 13 | defaultHeight: '1.2em' 14 | }) 15 | 16 | Vue.use(ToastPlugin) 17 | 18 | Vue.config.devtools = true 19 | 20 | window.$message = function (text) { 21 | Vue.$vux.toast.show({ text, type: 'text' }) 22 | } 23 | 24 | new Vue({ 25 | el: '#app', 26 | render: h => h(App) 27 | }) 28 | 29 | -------------------------------------------------------------------------------- /template/build/config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 需要构建的页面 一次只构建一个页面 3 | */ 4 | const pageName = require('../page') 5 | 6 | const notUseVendor = [] // 不使用公共资源的页面集合 7 | const notExtractCss = [] // 不抽取css的页面 8 | const useAbsolutePath = { // 使用绝对路径的页面 9 | example: '//cdn.com/' 10 | } 11 | 12 | module.exports = { 13 | pageName: pageName, 14 | useVendor: notUseVendor.indexOf(pageName) === -1, // 是否使用公共资源 需要先运行 np run vendor 15 | sourceMap: false, // 生产环境下是否需要js生成sourceMap 16 | extractCss: notExtractCss.indexOf(pageName) === -1, // 是否抽取出css 17 | // 资源引用路径是否为绝对路径 默认为相对路径 18 | // cdn 地址 绝对路径的地址 如果没有cdn域名请填写 / 默认是相对路径 false 19 | absolutePath: useAbsolutePath[pageName] == undefined ? false : useAbsolutePath[pageName], 20 | browsers: ['ios > 7', 'android > 4.1'] 21 | } -------------------------------------------------------------------------------- /template/src/view/index/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | index 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /template/src/common/icons/face.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | 3 | var icon = require('vue-svgicon') 4 | icon.register({ 5 | 'face': { 6 | width: 200, 7 | height: 200, 8 | viewBox: '0 0 1024 1024', 9 | data: `` 10 | } 11 | }) 12 | -------------------------------------------------------------------------------- /template/build/server.js: -------------------------------------------------------------------------------- 1 | const express = require('express') 2 | const webpack = require('webpack') 3 | const config = require('./webpack.dev.js') 4 | 5 | const app = express() 6 | const compiler = webpack(config) 7 | 8 | var devMiddleware = require('webpack-dev-middleware')(compiler, { 9 | publicPath: config.output.publicPath, 10 | // stats: { 11 | // colors: true, 12 | // chunks: false, 13 | // children: false, 14 | // chunks: false, 15 | // chunkModules: false 16 | // } 17 | log: false, 18 | heartbeat: 2000 19 | }) 20 | var hotMiddleware = require('webpack-hot-middleware')(compiler) 21 | compiler.plugin('compilation', function (compilation) { 22 | compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) { 23 | // console.log(data) 24 | // hotMiddleware.publish({ action: 'reload' }) 25 | cb() 26 | }) 27 | }) 28 | 29 | app.use(require('connect-history-api-fallback')()) 30 | app.use(devMiddleware) 31 | app.use(hotMiddleware) 32 | // serve pure static assets 33 | app.use('/lib', express.static('./lib')) 34 | // mobile visit in one wifi 35 | app.listen(8080, '0.0.0.0', function (err) { 36 | if (err) { 37 | console.log(err) 38 | return 39 | } 40 | console.log('Listening at http://localhost:8080') 41 | }) 42 | -------------------------------------------------------------------------------- /template/README.md: -------------------------------------------------------------------------------- 1 | ### 多页面vue2/webpack2构建配置 2 | 3 | 使用vue来写一些单页面很舒服,官方也有很健全的配置starter,但一般在业务生产中都不可能是单页面,往往需要做很多页面,需要 4 | 多人来配合来写,这个时候就需要进行项目的工程化,特别是针对前后端分离的项目,后端只提供json格式的数据,前端负责渲染页面和各种 5 | 路由处理,所以需要一个多页面的配置来进行开发指导,这个项目需要是实现的功能如下: 6 | 7 | 1. 使用ES6(并且使用webpack2的tree-shaking功能进行缩减代码) 8 | 2. 组件化`*.vue`开发 9 | 3. 功能模块化 10 | 4. 静态资源压缩 11 | 5. 静态资源破缓存(url?hash)(`gulp + webpack`实现) 12 | 6. 开发环境下页面自动刷新或者热替换 13 | 7. 支持多页面 14 | 8. 公共资源缓存(`vendor`) 15 | 9. css去重(由`vux-loader实现`) 16 | 10. 支持vue的jsx写法 17 | 18 | #### 项目说明 19 | > -- page.js 编译页面配置(团队项目请把此文件加入.gitignore里面禁止提交此文件) 20 | 21 | > -- build 构建文件存放 22 | 23 | > -- dist 输出目录 把此文件放入cdn或者给后端 24 | 25 | >-- lib 全局使用的外部库 26 | 27 | >-- src 业务源代码 28 | >---- common 页面公共组件 29 | >---- view 页面源码 每个页面是个单独的文件夹 所使用的图片等资源在每个页面的文件夹里面 30 | 31 | 32 | ### 使用说明 33 | 团队里面每个人在开始开发页面之前,需要在`page.js`配置一下需要开发的页面 34 | 35 | ### 首先打包公共资源vendor, 公共资源配置在 `package.json`中,统一管理 36 | ``` 37 | npm run vendor 38 | ``` 39 | 如果生成的有css文件模块,需要在`manifest.json`文件里面把`css`模块的meta重写成{},不然最终编译后会带有css文件 40 | 41 | 开发环境下使用 42 | ```bash 43 | npm run dev 44 | ``` 45 | 命令进行开发,在浏览器里面打开[0.0.0.0:8080](http://0.0.0.0:8080),已配置自动刷新和热替换 46 | 47 | 开发完成后使用 48 | ```bash 49 | npm run build 50 | ``` 51 | 命令进行打包 `dist`文件夹里面即是最终的发布文件 -------------------------------------------------------------------------------- /template/build/webpack.dev.js: -------------------------------------------------------------------------------- 1 | var webpack = require('webpack') 2 | var config = require('./webpack.base.js') 3 | var cssLoaders = require('./css-loaders') 4 | var HtmlWebpackPlugin = require('html-webpack-plugin') 5 | var page = require('./config') 6 | var vueConfig = require('./vue-loader.config') 7 | var path = require('path') 8 | var vuxLoader = require('vux-loader') 9 | 10 | config.devtool = 'source-map' 11 | cssLoaders({ sourceMap: false, extract: false }).forEach(function (loader) { 12 | config.module.rules.push({ 13 | test: new RegExp('\\.' + loader.key + '$'), 14 | loader: loader.value 15 | }) 16 | }) 17 | 18 | config.entry.app = ['./build/dev-client', config.entry.app] 19 | config.output.publicPath = '/' 20 | config.plugins = config.plugins.concat([ 21 | new webpack.DefinePlugin({ 22 | 'process.env.NODE_ENV': JSON.stringify('development') 23 | }), 24 | new webpack.HotModuleReplacementPlugin(), 25 | new webpack.NoEmitOnErrorsPlugin(), 26 | new webpack.LoaderOptionsPlugin({ 27 | options: { 28 | context: path.resolve(__dirname, '../'), 29 | postcss: [require('autoprefixer')({ browsers: page.browsers })] 30 | } 31 | }), 32 | new HtmlWebpackPlugin({ 33 | filename: 'index.html', 34 | template: page.template, 35 | inject: true, 36 | path: '/' 37 | }) 38 | ]) 39 | 40 | // module.exports = config 41 | 42 | module.exports = vuxLoader.merge(config, { plugins: ['vux-ui'], showVuxVersionInfo: false }) -------------------------------------------------------------------------------- /template/build/webpack.base.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const webpack = require('webpack') 3 | const page = require('./config') 4 | const vueConfig = require('./vue-loader.config') 5 | 6 | process.env.BROWSERSLIST = page.browsers 7 | 8 | page.entry = { app: path.resolve(__dirname, '../src/view/' + page.pageName + '/main.js') } 9 | page.template = path.resolve(__dirname, '../src/view/' + page.pageName + '/template.html') 10 | 11 | module.exports = { 12 | entry: page.entry, 13 | output: { 14 | path: path.resolve(__dirname, '../dist/' + page.pageName + '/static'), 15 | publicPath: page.absolutePath ? page.absolutePath + page.pageName + '/static/' : './static/', 16 | filename: '[name].js' 17 | }, 18 | resolve: { 19 | extensions: ['.js', '.json', '.vue'] 20 | }, 21 | module: { 22 | rules: [ 23 | { 24 | test: /\.vue$/, 25 | loader: 'vue-loader', 26 | options: vueConfig 27 | }, 28 | { 29 | test: /\.js$/, 30 | loader: 'babel-loader', 31 | exclude: /node_modules/ 32 | }, 33 | { 34 | test: /\.(png|jpg|gif|svg)$/, 35 | loader: 'url-loader', 36 | options: { 37 | limit: 8000, 38 | name: '[name].[ext]?[hash:7]' 39 | } 40 | } 41 | ] 42 | }, 43 | plugins: [ 44 | new webpack.HashedModuleIdsPlugin() 45 | ], 46 | node: { // to fix css-loader add node-shim 47 | Buffer: false 48 | } 49 | } 50 | 51 | if (page.useVendor) { 52 | module.exports.plugins.push(new webpack.DllReferencePlugin({ 53 | context: __dirname, 54 | manifest: require('../manifest.json') 55 | })) 56 | } -------------------------------------------------------------------------------- /template/build/css-loaders.js: -------------------------------------------------------------------------------- 1 | const ExtractTextPlugin = require('extract-text-webpack-plugin') 2 | const page = require('./config') 3 | 4 | module.exports = function (options) { 5 | // generate loader string to be used with extract text plugin 6 | function generateLoaders (loaders) { 7 | var sourceLoader = loaders.map(function (loader) { 8 | var extraParamChar 9 | if (/\?/.test(loader)) { 10 | loader = loader.replace(/\?/, '-loader?') 11 | extraParamChar = '&' 12 | } else { 13 | loader = loader + '-loader' 14 | extraParamChar = '?' 15 | } 16 | return loader + (options.sourceMap ? extraParamChar + 'sourceMap' : '') 17 | }).join('!') 18 | 19 | if (options.extract) { 20 | // override publicPath 21 | return ExtractTextPlugin.extract({ 22 | fallback: 'style-loader', 23 | use: sourceLoader, 24 | publicPath: page.absolutePath ? undefined : './' 25 | }) 26 | } else { 27 | return ['style-loader', sourceLoader].join('!') 28 | } 29 | } 30 | 31 | // http://vuejs.github.io/vue-loader/configurations/extract-css.html 32 | return [ 33 | { 34 | key: 'css', 35 | value: generateLoaders(['css', 'postcss']) 36 | }, 37 | { 38 | key: 'less', 39 | value: generateLoaders(['css', 'postcss', 'less']) 40 | }, 41 | { 42 | key: 'sass', 43 | value: generateLoaders(['css', 'postcss', 'sass']) 44 | }, 45 | { 46 | key: 'scss', 47 | value: generateLoaders(['css', 'postcss', 'sass']) 48 | }, 49 | { 50 | key: 'stylus', 51 | value: generateLoaders(['css', 'postcss', 'stylus']) 52 | }, 53 | { 54 | key: 'styl', 55 | value: generateLoaders(['css', 'postcss', 'stylus']) 56 | } 57 | ] 58 | } 59 | -------------------------------------------------------------------------------- /template/src/common/components/Dialog.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 28 | 29 | -------------------------------------------------------------------------------- /template/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "webpack-mutiple", 3 | "description": "A Vue.js project", 4 | "author": "agileago ", 5 | "version": "0.0.1", 6 | "private": true, 7 | "vendor": [ 8 | "animejs", 9 | "vue", 10 | "es6-promise", 11 | "weui" 12 | ], 13 | "scripts": { 14 | "dev": "node build/server.js", 15 | "build": "webpack --hide-modules --config build/webpack.prod.js && ncp lib dist/lib && gulp", 16 | "vendor": "rm -rf lib/vendor && webpack --config build/webpack.dll.js", 17 | "cplib": "ncp lib dist/lib", 18 | "svg": "vsvg -s ./src/common/svg/ -t ./src/common/icons/" 19 | }, 20 | "dependencies": { 21 | "animejs": "^2.0.2", 22 | "es6-promise": "^4.1.1", 23 | "vue": "^2.4.2", 24 | "vue-svgicon": "^2.1.0", 25 | "vux": "^2.5.3", 26 | "weui": "^1.1.2" 27 | }, 28 | "devDependencies": { 29 | "autoprefixer": "^6.7.7", 30 | "babel-core": "^6.25.0", 31 | "babel-loader": "^7.1.1", 32 | "babel-preset-es2015": "^6.24.1", 33 | "babel-preset-stage-2": "^6.24.1", 34 | "connect-history-api-fallback": "^1.3.0", 35 | "css-loader": "^0.28.4", 36 | "eventsource-polyfill": "^0.9.6", 37 | "express": "^4.15.3", 38 | "extract-text-webpack-plugin": "^3.0.0", 39 | "file-loader": "^0.11.2", 40 | "gulp": "^3.9.1", 41 | "gulp-rev-hash3": "^1.0.9", 42 | "html-webpack-plugin": "^2.29.0", 43 | "less": "^2.7.2", 44 | "less-loader": "^4.0.5", 45 | "ncp": "^2.0.0", 46 | "postcss-loader": "^1.3.3", 47 | "rimraf": "^2.6.1", 48 | "style-loader": "^0.18.2", 49 | "url-loader": "^0.5.9", 50 | "vue-loader": "^12.2.2", 51 | "vue-template-compiler": "^2.4.2", 52 | "vux-loader": "^1.1.2", 53 | "webpack": "^3.3.0", 54 | "webpack-dev-middleware": "^1.11.0", 55 | "webpack-hot-middleware": "^2.18.2" 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /template/src/common/svg/face.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /template/build/webpack.prod.js: -------------------------------------------------------------------------------- 1 | process.env.NODE_ENV = 'production' 2 | 3 | var webpack = require('webpack') 4 | var config = require('./webpack.base.js') 5 | var cssLoaders = require('./css-loaders') 6 | var ExtractTextPlugin = require('extract-text-webpack-plugin') 7 | var HtmlWebpackPlugin = require('html-webpack-plugin') 8 | var page = require('./config') 9 | var rimraf = require('rimraf') 10 | var path = require('path') 11 | var vueConfig = require('./vue-loader.config') 12 | var vuxLoader = require('vux-loader') 13 | 14 | config.output.filename = '[name].js' 15 | config.output.chunkFilename = '[id].js?[chunkhash:7]' 16 | config.devtool = page.sourceMap ? 'source-map' : false 17 | 18 | vueConfig.loaders = vueConfig.loaders || {} 19 | cssLoaders({ sourceMap: false, extract: page.extractCss }).forEach(function (loader) { 20 | if (page.extractCss) { 21 | vueConfig.loaders[loader.key] = loader.value 22 | } 23 | config.module.rules.push({ 24 | test: new RegExp('\\.' + loader.key + '$'), 25 | loader: loader.value 26 | }) 27 | }) 28 | 29 | if (page.extractCss) { 30 | config.plugins.push(new ExtractTextPlugin('[name].css')) 31 | } 32 | 33 | config.plugins = config.plugins.concat([ 34 | new webpack.DefinePlugin({ 35 | 'process.env.NODE_ENV': JSON.stringify('production') 36 | }), 37 | new webpack.LoaderOptionsPlugin({ 38 | minimize: true, 39 | options: { 40 | context: path.resolve(__dirname, '../'), 41 | postcss: [require('autoprefixer')({ browsers: page.browsers })] 42 | } 43 | }), 44 | new webpack.optimize.UglifyJsPlugin({ 45 | sourceMap: page.sourceMap, 46 | compress: { 47 | warnings: false 48 | } 49 | }), 50 | new HtmlWebpackPlugin({ 51 | filename: '../index.html', 52 | template: page.template, 53 | inject: true, 54 | hash: true, 55 | path: page.absolutePath ? page.absolutePath : '../' 56 | }) 57 | ]) 58 | 59 | rimraf.sync(path.resolve(__dirname, '../dist/' + page.pageName)) 60 | 61 | module.exports = vuxLoader.merge(config, { plugins: ['vux-ui', 'duplicate-style'] }) 62 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # webpack-mutiple 2 | ### vue多页面开发脚手架 3 | 4 | vue官方只提供了单页面的脚手架,但我们可以根据它来改造成多页面,开发的时候我们每次只开发一个页面,而不是同时开发多个页面,所以项目根路径下应该有个配置js,来指明这次要开发的页面 5 | 6 | ### 工具推荐 7 | 1. 最新版webstorm 8 | 2. 使用[yarn](https://yarnpkg.com/)安装依赖(提供lock功能) 国内用户请使用淘宝源 9 | `yarn config set registry https://registry.npm.taobao.org` 10 | 3. node-sass安装失败解决方案 11 | `SASS_BINARY_SITE=https://npm.taobao.org/mirrors/node-sass/ npm install node-sass` 12 | 13 | ### 使用 14 | 15 | 这是一个[vue-cli](https://github.com/vuejs/vue-cli).的项目模板 16 | 17 | ``` bash 18 | $ npm install -g vue-cli 19 | $ vue init agileago/webpack-mutiple my-project 20 | $ cd my-project 21 | $ npm install (或者 yarn) 22 | $ npm run vendor 23 | $ npm run dev 24 | $ npm run build 25 | ``` 26 | 27 | ### 多页面如何配置 28 | 29 | 配置在`config.js`里面 30 | 31 | 32 | ``` javascript 33 | /** 34 | * 需要构建的页面 一次只构建一个页面 35 | */ 36 | const pageName = 'index' 37 | 38 | // 大部分情况下都是默认配置 39 | 40 | const notUseVendor = [] // 不使用公共资源的页面集合 41 | const notExtractCss = [] // 不抽取css的页面 42 | const useAbsolutePath = { // 使用绝对路径的页面 43 | example: '//cdn.com/' 44 | } 45 | 46 | module.exports = { 47 | pageName: pageName, 48 | useVendor: notUseVendor.indexOf(pageName) === -1, // 是否使用公共资源 需要先运行 np run vendor 49 | extractCss: notExtractCss.indexOf(pageName) === -1, // 是否抽取出css 50 | // 资源引用路径是否为绝对路径 默认为相对路径 51 | // cdn 地址 绝对路径的地址 如果没有cdn域名请填写 / 默认是相对路径 false 52 | absolutePath: useAbsolutePath[pageName] == undefined ? false : useAbsolutePath[pageName], 53 | sourceMap: false, // 生产环境下是否需要js生成sourceMap 54 | browsers: ['ios > 7', 'android > 4.1'] 55 | } 56 | ``` 57 | 58 | ### 公共资源 vendor 59 | 多个页面需要共享资源库,利用webpack的dll功能生成vendor, vendor的配置在 `package.json`中的`vendor`选项 60 | 61 | ``` json 62 | "vendor": [ 63 | "vue", 64 | "es6-promise", 65 | "weui" 66 | ], 67 | ``` 68 | 69 | ### 生成页面 70 | 每做一个新页面需要在`src/views/`下面生成一个页面文件夹,文件夹里面需要包含一个入口文件 `main.js` 和页面模板文件 `template.html`,具体请看`index`示例页面 71 | 72 | ### tips 73 | 74 | 当想在工程里面引入`node_modules`下工程某些源代码,但这些源代码有可能是es6语法的,可直接在webpack的 75 | loader里面添加 76 | ```javascript 77 | { 78 | test: /vux.src.*?js$/, 79 | loader: 'babel-loader' 80 | } 81 | ``` 82 | 就是模块名 . 源码文件夹 js文件 83 | -------------------------------------------------------------------------------- /template/build/webpack.dll.js: -------------------------------------------------------------------------------- 1 | const webpack = require('webpack') 2 | const path = require('path') 3 | var ExtractTextPlugin = require('extract-text-webpack-plugin') 4 | var page = require('./config') 5 | var cssLoaders = require('./css-loaders') 6 | var vueConfig = require('./vue-loader.config') 7 | var vendor = require('../package.json').vendor 8 | 9 | const config = { 10 | entry: { 11 | vendor: vendor 12 | }, 13 | output: { 14 | path: path.resolve(__dirname, '../lib/vendor'), 15 | filename: '[name].common.js', 16 | library: '[name]_common' 17 | }, 18 | plugins: [ 19 | new webpack.DefinePlugin({ 'process.env.NODE_ENV': JSON.stringify('production') }), 20 | new webpack.DllPlugin({ 21 | path: path.resolve(__dirname, '../manifest.json'), 22 | name: '[name]_common', 23 | context: __dirname 24 | }), 25 | new ExtractTextPlugin('[name].common.css'), 26 | new webpack.LoaderOptionsPlugin({ 27 | minimize: true, 28 | options: { 29 | context: path.resolve(__dirname, '../'), 30 | postcss: [require('autoprefixer')({ browsers: page.browsers })] 31 | } 32 | }), 33 | new webpack.optimize.UglifyJsPlugin({ 34 | sourceMap: false, 35 | compress: { 36 | warnings: false 37 | } 38 | }), 39 | new webpack.HashedModuleIdsPlugin() 40 | ], 41 | module: { 42 | rules: [ 43 | { 44 | test: /\.vue$/, 45 | loader: 'vue-loader', 46 | options: vueConfig 47 | }, 48 | { 49 | test: /\.js$/, 50 | loader: 'babel-loader', 51 | exclude: /node_modules/ 52 | }, 53 | { 54 | test: /\.(png|jpg|gif|svg)$/, 55 | loader: 'url-loader', 56 | options: { 57 | limit: 8000, 58 | name: '[name].[ext]?[hash:7]' 59 | } 60 | } 61 | ] 62 | }, 63 | node: { 64 | Buffer: false 65 | } 66 | } 67 | 68 | // 注入cssloader 69 | vueConfig.loaders = vueConfig.loaders || {} 70 | cssLoaders({ sourceMap: false , extract: true }).forEach(function (loader) { 71 | vueConfig.loaders[loader.key] = loader.value 72 | config.module.rules.push({ 73 | test: new RegExp('\\.' + loader.key + '$'), 74 | loader: loader.value 75 | }) 76 | }) 77 | 78 | module.exports = config -------------------------------------------------------------------------------- /template/src/view/index/components/App.vue: -------------------------------------------------------------------------------- 1 | 24 | 25 | 46 | 47 | -------------------------------------------------------------------------------- /template/lib/zepto.min.js: -------------------------------------------------------------------------------- 1 | /*! Zepto 1.1.6 (generated with Zepto Builder) - zepto event ajax form deferred callbacks - zeptojs.com/license */ 2 | var Zepto=function(){function t(t){return null==t?String(t):J[X.call(t)]||"object"}function e(e){return"function"==t(e)}function n(t){return null!=t&&t==t.window}function r(t){return null!=t&&t.nodeType==t.DOCUMENT_NODE}function i(e){return"object"==t(e)}function o(t){return i(t)&&!n(t)&&Object.getPrototypeOf(t)==Object.prototype}function s(t){return"number"==typeof t.length}function a(t){return A.call(t,function(t){return null!=t})}function u(t){return t.length>0?T.fn.concat.apply([],t):t}function c(t){return t.replace(/::/g,"/").replace(/([A-Z]+)([A-Z][a-z])/g,"$1_$2").replace(/([a-z\d])([A-Z])/g,"$1_$2").replace(/_/g,"-").toLowerCase()}function l(t){return t in Z?Z[t]:Z[t]=new RegExp("(^|\\s)"+t+"(\\s|$)")}function f(t,e){return"number"!=typeof e||$[c(t)]?e:e+"px"}function h(t){var e,n;return L[t]||(e=D.createElement(t),D.body.appendChild(e),n=getComputedStyle(e,"").getPropertyValue("display"),e.parentNode.removeChild(e),"none"==n&&(n="block"),L[t]=n),L[t]}function p(t){return"children"in t?k.call(t.children):T.map(t.childNodes,function(t){return 1==t.nodeType?t:void 0})}function d(t,e){var n,r=t?t.length:0;for(n=0;r>n;n++)this[n]=t[n];this.length=r,this.selector=e||""}function m(t,e,n){for(j in e)n&&(o(e[j])||Q(e[j]))?(o(e[j])&&!o(t[j])&&(t[j]={}),Q(e[j])&&!Q(t[j])&&(t[j]=[]),m(t[j],e[j],n)):e[j]!==E&&(t[j]=e[j])}function g(t,e){return null==e?T(t):T(t).filter(e)}function v(t,n,r,i){return e(n)?n.call(t,r,i):n}function y(t,e,n){null==n?t.removeAttribute(e):t.setAttribute(e,n)}function b(t,e){var n=t.className||"",r=n&&n.baseVal!==E;return e===E?r?n.baseVal:n:void(r?n.baseVal=e:t.className=e)}function x(t){try{return t?"true"==t||("false"==t?!1:"null"==t?null:+t+""==t?+t:/^[\[\{]/.test(t)?T.parseJSON(t):t):t}catch(e){return t}}function w(t,e){e(t);for(var n=0,r=t.childNodes.length;r>n;n++)w(t.childNodes[n],e)}var E,j,T,C,S,N,O=[],P=O.concat,A=O.filter,k=O.slice,D=window.document,L={},Z={},$={"column-count":1,columns:1,"font-weight":1,"line-height":1,opacity:1,"z-index":1,zoom:1},F=/^\s*<(\w+|!)[^>]*>/,M=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,R=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,q=/^(?:body|html)$/i,z=/([A-Z])/g,W=["val","css","html","text","data","width","height","offset"],H=["after","prepend","before","append"],I=D.createElement("table"),_=D.createElement("tr"),B={tr:D.createElement("tbody"),tbody:I,thead:I,tfoot:I,td:_,th:_,"*":D.createElement("div")},V=/complete|loaded|interactive/,U=/^[\w-]*$/,J={},X=J.toString,Y={},G=D.createElement("div"),K={tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},Q=Array.isArray||function(t){return t instanceof Array};return Y.matches=function(t,e){if(!e||!t||1!==t.nodeType)return!1;var n=t.webkitMatchesSelector||t.mozMatchesSelector||t.oMatchesSelector||t.matchesSelector;if(n)return n.call(t,e);var r,i=t.parentNode,o=!i;return o&&(i=G).appendChild(t),r=~Y.qsa(i,e).indexOf(t),o&&G.removeChild(t),r},S=function(t){return t.replace(/-+(.)?/g,function(t,e){return e?e.toUpperCase():""})},N=function(t){return A.call(t,function(e,n){return t.indexOf(e)==n})},Y.fragment=function(t,e,n){var r,i,s;return M.test(t)&&(r=T(D.createElement(RegExp.$1))),r||(t.replace&&(t=t.replace(R,"<$1>")),e===E&&(e=F.test(t)&&RegExp.$1),e in B||(e="*"),s=B[e],s.innerHTML=""+t,r=T.each(k.call(s.childNodes),function(){s.removeChild(this)})),o(n)&&(i=T(r),T.each(n,function(t,e){W.indexOf(t)>-1?i[t](e):i.attr(t,e)})),r},Y.Z=function(t,e){return new d(t,e)},Y.isZ=function(t){return t instanceof Y.Z},Y.init=function(t,n){var r;if(!t)return Y.Z();if("string"==typeof t)if(t=t.trim(),"<"==t[0]&&F.test(t))r=Y.fragment(t,RegExp.$1,n),t=null;else{if(n!==E)return T(n).find(t);r=Y.qsa(D,t)}else{if(e(t))return T(D).ready(t);if(Y.isZ(t))return t;if(Q(t))r=a(t);else if(i(t))r=[t],t=null;else if(F.test(t))r=Y.fragment(t.trim(),RegExp.$1,n),t=null;else{if(n!==E)return T(n).find(t);r=Y.qsa(D,t)}}return Y.Z(r,t)},T=function(t,e){return Y.init(t,e)},T.extend=function(t){var e,n=k.call(arguments,1);return"boolean"==typeof t&&(e=t,t=n.shift()),n.forEach(function(n){m(t,n,e)}),t},Y.qsa=function(t,e){var n,r="#"==e[0],i=!r&&"."==e[0],o=r||i?e.slice(1):e,s=U.test(o);return t.getElementById&&s&&r?(n=t.getElementById(o))?[n]:[]:1!==t.nodeType&&9!==t.nodeType&&11!==t.nodeType?[]:k.call(s&&!r&&t.getElementsByClassName?i?t.getElementsByClassName(o):t.getElementsByTagName(e):t.querySelectorAll(e))},T.contains=D.documentElement.contains?function(t,e){return t!==e&&t.contains(e)}:function(t,e){for(;e&&(e=e.parentNode);)if(e===t)return!0;return!1},T.type=t,T.isFunction=e,T.isWindow=n,T.isArray=Q,T.isPlainObject=o,T.isEmptyObject=function(t){var e;for(e in t)return!1;return!0},T.inArray=function(t,e,n){return O.indexOf.call(e,t,n)},T.camelCase=S,T.trim=function(t){return null==t?"":String.prototype.trim.call(t)},T.uuid=0,T.support={},T.expr={},T.noop=function(){},T.map=function(t,e){var n,r,i,o=[];if(s(t))for(r=0;r=0?t:t+this.length]},toArray:function(){return this.get()},size:function(){return this.length},remove:function(){return this.each(function(){null!=this.parentNode&&this.parentNode.removeChild(this)})},each:function(t){return O.every.call(this,function(e,n){return t.call(e,n,e)!==!1}),this},filter:function(t){return e(t)?this.not(this.not(t)):T(A.call(this,function(e){return Y.matches(e,t)}))},add:function(t,e){return T(N(this.concat(T(t,e))))},is:function(t){return this.length>0&&Y.matches(this[0],t)},not:function(t){var n=[];if(e(t)&&t.call!==E)this.each(function(e){t.call(this,e)||n.push(this)});else{var r="string"==typeof t?this.filter(t):s(t)&&e(t.item)?k.call(t):T(t);this.forEach(function(t){r.indexOf(t)<0&&n.push(t)})}return T(n)},has:function(t){return this.filter(function(){return i(t)?T.contains(this,t):T(this).find(t).size()})},eq:function(t){return-1===t?this.slice(t):this.slice(t,+t+1)},first:function(){var t=this[0];return t&&!i(t)?t:T(t)},last:function(){var t=this[this.length-1];return t&&!i(t)?t:T(t)},find:function(t){var e,n=this;return e=t?"object"==typeof t?T(t).filter(function(){var t=this;return O.some.call(n,function(e){return T.contains(e,t)})}):1==this.length?T(Y.qsa(this[0],t)):this.map(function(){return Y.qsa(this,t)}):T()},closest:function(t,e){var n=this[0],i=!1;for("object"==typeof t&&(i=T(t));n&&!(i?i.indexOf(n)>=0:Y.matches(n,t));)n=n!==e&&!r(n)&&n.parentNode;return T(n)},parents:function(t){for(var e=[],n=this;n.length>0;)n=T.map(n,function(t){return(t=t.parentNode)&&!r(t)&&e.indexOf(t)<0?(e.push(t),t):void 0});return g(e,t)},parent:function(t){return g(N(this.pluck("parentNode")),t)},children:function(t){return g(this.map(function(){return p(this)}),t)},contents:function(){return this.map(function(){return this.contentDocument||k.call(this.childNodes)})},siblings:function(t){return g(this.map(function(t,e){return A.call(p(e.parentNode),function(t){return t!==e})}),t)},empty:function(){return this.each(function(){this.innerHTML=""})},pluck:function(t){return T.map(this,function(e){return e[t]})},show:function(){return this.each(function(){"none"==this.style.display&&(this.style.display=""),"none"==getComputedStyle(this,"").getPropertyValue("display")&&(this.style.display=h(this.nodeName))})},replaceWith:function(t){return this.before(t).remove()},wrap:function(t){var n=e(t);if(this[0]&&!n)var r=T(t).get(0),i=r.parentNode||this.length>1;return this.each(function(e){T(this).wrapAll(n?t.call(this,e):i?r.cloneNode(!0):r)})},wrapAll:function(t){if(this[0]){T(this[0]).before(t=T(t));for(var e;(e=t.children()).length;)t=e.first();T(t).append(this)}return this},wrapInner:function(t){var n=e(t);return this.each(function(e){var r=T(this),i=r.contents(),o=n?t.call(this,e):t;i.length?i.wrapAll(o):r.append(o)})},unwrap:function(){return this.parent().each(function(){T(this).replaceWith(T(this).children())}),this},clone:function(){return this.map(function(){return this.cloneNode(!0)})},hide:function(){return this.css("display","none")},toggle:function(t){return this.each(function(){var e=T(this);(t===E?"none"==e.css("display"):t)?e.show():e.hide()})},prev:function(t){return T(this.pluck("previousElementSibling")).filter(t||"*")},next:function(t){return T(this.pluck("nextElementSibling")).filter(t||"*")},html:function(t){return 0 in arguments?this.each(function(e){var n=this.innerHTML;T(this).empty().append(v(this,t,e,n))}):0 in this?this[0].innerHTML:null},text:function(t){return 0 in arguments?this.each(function(e){var n=v(this,t,e,this.textContent);this.textContent=null==n?"":""+n}):0 in this?this.pluck("textContent").join(""):null},attr:function(t,e){var n;return"string"!=typeof t||1 in arguments?this.each(function(n){if(1===this.nodeType)if(i(t))for(j in t)y(this,j,t[j]);else y(this,t,v(this,e,n,this.getAttribute(t)))}):this.length&&1===this[0].nodeType?!(n=this[0].getAttribute(t))&&t in this[0]?this[0][t]:n:E},removeAttr:function(t){return this.each(function(){1===this.nodeType&&t.split(" ").forEach(function(t){y(this,t)},this)})},prop:function(t,e){return t=K[t]||t,1 in arguments?this.each(function(n){this[t]=v(this,e,n,this[t])}):this[0]&&this[0][t]},data:function(t,e){var n="data-"+t.replace(z,"-$1").toLowerCase(),r=1 in arguments?this.attr(n,e):this.attr(n);return null!==r?x(r):E},val:function(t){return 0 in arguments?this.each(function(e){this.value=v(this,t,e,this.value)}):this[0]&&(this[0].multiple?T(this[0]).find("option").filter(function(){return this.selected}).pluck("value"):this[0].value)},offset:function(t){if(t)return this.each(function(e){var n=T(this),r=v(this,t,e,n.offset()),i=n.offsetParent().offset(),o={top:r.top-i.top,left:r.left-i.left};"static"==n.css("position")&&(o.position="relative"),n.css(o)});if(!this.length)return null;if(!T.contains(D.documentElement,this[0]))return{top:0,left:0};var e=this[0].getBoundingClientRect();return{left:e.left+window.pageXOffset,top:e.top+window.pageYOffset,width:Math.round(e.width),height:Math.round(e.height)}},css:function(e,n){if(arguments.length<2){var r,i=this[0];if(!i)return;if(r=getComputedStyle(i,""),"string"==typeof e)return i.style[S(e)]||r.getPropertyValue(e);if(Q(e)){var o={};return T.each(e,function(t,e){o[e]=i.style[S(e)]||r.getPropertyValue(e)}),o}}var s="";if("string"==t(e))n||0===n?s=c(e)+":"+f(e,n):this.each(function(){this.style.removeProperty(c(e))});else for(j in e)e[j]||0===e[j]?s+=c(j)+":"+f(j,e[j])+";":this.each(function(){this.style.removeProperty(c(j))});return this.each(function(){this.style.cssText+=";"+s})},index:function(t){return t?this.indexOf(T(t)[0]):this.parent().children().indexOf(this[0])},hasClass:function(t){return t?O.some.call(this,function(t){return this.test(b(t))},l(t)):!1},addClass:function(t){return t?this.each(function(e){if("className"in this){C=[];var n=b(this),r=v(this,t,e,n);r.split(/\s+/g).forEach(function(t){T(this).hasClass(t)||C.push(t)},this),C.length&&b(this,n+(n?" ":"")+C.join(" "))}}):this},removeClass:function(t){return this.each(function(e){if("className"in this){if(t===E)return b(this,"");C=b(this),v(this,t,e,C).split(/\s+/g).forEach(function(t){C=C.replace(l(t)," ")}),b(this,C.trim())}})},toggleClass:function(t,e){return t?this.each(function(n){var r=T(this),i=v(this,t,n,b(this));i.split(/\s+/g).forEach(function(t){(e===E?!r.hasClass(t):e)?r.addClass(t):r.removeClass(t)})}):this},scrollTop:function(t){if(this.length){var e="scrollTop"in this[0];return t===E?e?this[0].scrollTop:this[0].pageYOffset:this.each(e?function(){this.scrollTop=t}:function(){this.scrollTo(this.scrollX,t)})}},scrollLeft:function(t){if(this.length){var e="scrollLeft"in this[0];return t===E?e?this[0].scrollLeft:this[0].pageXOffset:this.each(e?function(){this.scrollLeft=t}:function(){this.scrollTo(t,this.scrollY)})}},position:function(){if(this.length){var t=this[0],e=this.offsetParent(),n=this.offset(),r=q.test(e[0].nodeName)?{top:0,left:0}:e.offset();return n.top-=parseFloat(T(t).css("margin-top"))||0,n.left-=parseFloat(T(t).css("margin-left"))||0,r.top+=parseFloat(T(e[0]).css("border-top-width"))||0,r.left+=parseFloat(T(e[0]).css("border-left-width"))||0,{top:n.top-r.top,left:n.left-r.left}}},offsetParent:function(){return this.map(function(){for(var t=this.offsetParent||D.body;t&&!q.test(t.nodeName)&&"static"==T(t).css("position");)t=t.offsetParent;return t})}},T.fn.detach=T.fn.remove,["width","height"].forEach(function(t){var e=t.replace(/./,function(t){return t[0].toUpperCase()});T.fn[t]=function(i){var o,s=this[0];return i===E?n(s)?s["inner"+e]:r(s)?s.documentElement["scroll"+e]:(o=this.offset())&&o[t]:this.each(function(e){s=T(this),s.css(t,v(this,i,e,s[t]()))})}}),H.forEach(function(e,n){var r=n%2;T.fn[e]=function(){var e,i,o=T.map(arguments,function(n){return e=t(n),"object"==e||"array"==e||null==n?n:Y.fragment(n)}),s=this.length>1;return o.length<1?this:this.each(function(t,e){i=r?e:e.parentNode,e=0==n?e.nextSibling:1==n?e.firstChild:2==n?e:null;var a=T.contains(D.documentElement,i);o.forEach(function(t){if(s)t=t.cloneNode(!0);else if(!i)return T(t).remove();i.insertBefore(t,e),a&&w(t,function(t){null==t.nodeName||"SCRIPT"!==t.nodeName.toUpperCase()||t.type&&"text/javascript"!==t.type||t.src||window.eval.call(window,t.innerHTML)})})})},T.fn[r?e+"To":"insert"+(n?"Before":"After")]=function(t){return T(t)[e](this),this}}),Y.Z.prototype=d.prototype=T.fn,Y.uniq=N,Y.deserializeValue=x,T.zepto=Y,T}();window.Zepto=Zepto,void 0===window.$&&(window.$=Zepto),function(t){function e(e,n,r){var i=t.Event(n);return t(e).trigger(i,r),!i.isDefaultPrevented()}function n(t,n,r,i){return t.global?e(n||y,r,i):void 0}function r(e){e.global&&0===t.active++&&n(e,null,"ajaxStart")}function i(e){e.global&&!--t.active&&n(e,null,"ajaxStop")}function o(t,e){var r=e.context;return e.beforeSend.call(r,t,e)===!1||n(e,r,"ajaxBeforeSend",[t,e])===!1?!1:void n(e,r,"ajaxSend",[t,e])}function s(t,e,r,i){var o=r.context,s="success";r.success.call(o,t,s,e),i&&i.resolveWith(o,[t,s,e]),n(r,o,"ajaxSuccess",[e,r,t]),u(s,e,r)}function a(t,e,r,i,o){var s=i.context;i.error.call(s,r,e,t),o&&o.rejectWith(s,[r,e,t]),n(i,s,"ajaxError",[r,i,t||e]),u(e,r,i)}function u(t,e,r){var o=r.context;r.complete.call(o,e,t),n(r,o,"ajaxComplete",[e,r]),i(r)}function c(){}function l(t){return t&&(t=t.split(";",2)[0]),t&&(t==j?"html":t==E?"json":x.test(t)?"script":w.test(t)&&"xml")||"text"}function f(t,e){return""==e?t:(t+"&"+e).replace(/[&?]{1,2}/,"?")}function h(e){e.processData&&e.data&&"string"!=t.type(e.data)&&(e.data=t.param(e.data,e.traditional)),!e.data||e.type&&"GET"!=e.type.toUpperCase()||(e.url=f(e.url,e.data),e.data=void 0)}function p(e,n,r,i){return t.isFunction(n)&&(i=r,r=n,n=void 0),t.isFunction(r)||(i=r,r=void 0),{url:e,data:n,success:r,dataType:i}}function d(e,n,r,i){var o,s=t.isArray(n),a=t.isPlainObject(n);t.each(n,function(n,u){o=t.type(u),i&&(n=r?i:i+"["+(a||"object"==o||"array"==o?n:"")+"]"),!i&&s?e.add(u.name,u.value):"array"==o||!r&&"object"==o?d(e,u,r,n):e.add(n,u)})}var m,g,v=0,y=window.document,b=/)<[^<]*)*<\/script>/gi,x=/^(?:text|application)\/javascript/i,w=/^(?:text|application)\/xml/i,E="application/json",j="text/html",T=/^\s*$/,C=y.createElement("a");C.href=window.location.href,t.active=0,t.ajaxJSONP=function(e,n){if(!("type"in e))return t.ajax(e);var r,i,u=e.jsonpCallback,c=(t.isFunction(u)?u():u)||"jsonp"+ ++v,l=y.createElement("script"),f=window[c],h=function(e){t(l).triggerHandler("error",e||"abort")},p={abort:h};return n&&n.promise(p),t(l).on("load error",function(o,u){clearTimeout(i),t(l).off().remove(),"error"!=o.type&&r?s(r[0],p,e,n):a(null,u||"error",p,e,n),window[c]=f,r&&t.isFunction(f)&&f(r[0]),f=r=void 0}),o(p,e)===!1?(h("abort"),p):(window[c]=function(){r=arguments},l.src=e.url.replace(/\?(.+)=\?/,"?$1="+c),y.head.appendChild(l),e.timeout>0&&(i=setTimeout(function(){h("timeout")},e.timeout)),p)},t.ajaxSettings={type:"GET",beforeSend:c,success:c,error:c,complete:c,context:null,global:!0,xhr:function(){return new window.XMLHttpRequest},accepts:{script:"text/javascript, application/javascript, application/x-javascript",json:E,xml:"application/xml, text/xml",html:j,text:"text/plain"},crossDomain:!1,timeout:0,processData:!0,cache:!0},t.ajax=function(e){var n,i,u=t.extend({},e||{}),p=t.Deferred&&t.Deferred();for(m in t.ajaxSettings)void 0===u[m]&&(u[m]=t.ajaxSettings[m]);r(u),u.crossDomain||(n=y.createElement("a"),n.href=u.url,n.href=n.href,u.crossDomain=C.protocol+"//"+C.host!=n.protocol+"//"+n.host),u.url||(u.url=window.location.toString()),(i=u.url.indexOf("#"))>-1&&(u.url=u.url.slice(0,i)),h(u);var d=u.dataType,v=/\?.+=\?/.test(u.url);if(v&&(d="jsonp"),u.cache!==!1&&(e&&e.cache===!0||"script"!=d&&"jsonp"!=d)||(u.url=f(u.url,"_="+Date.now())),"jsonp"==d)return v||(u.url=f(u.url,u.jsonp?u.jsonp+"=?":u.jsonp===!1?"":"callback=?")),t.ajaxJSONP(u,p);var b,x=u.accepts[d],w={},E=function(t,e){w[t.toLowerCase()]=[t,e]},j=/^([\w-]+:)\/\//.test(u.url)?RegExp.$1:window.location.protocol,S=u.xhr(),N=S.setRequestHeader;if(p&&p.promise(S),u.crossDomain||E("X-Requested-With","XMLHttpRequest"),E("Accept",x||"*/*"),(x=u.mimeType||x)&&(x.indexOf(",")>-1&&(x=x.split(",",2)[0]),S.overrideMimeType&&S.overrideMimeType(x)),(u.contentType||u.contentType!==!1&&u.data&&"GET"!=u.type.toUpperCase())&&E("Content-Type",u.contentType||"application/x-www-form-urlencoded"),u.headers)for(g in u.headers)E(g,u.headers[g]);if(S.setRequestHeader=E,S.onreadystatechange=function(){if(4==S.readyState){S.onreadystatechange=c,clearTimeout(b);var e,n=!1;if(S.status>=200&&S.status<300||304==S.status||0==S.status&&"file:"==j){if(d=d||l(u.mimeType||S.getResponseHeader("content-type")),"arraybuffer"==S.responseType||"blob"==S.responseType)e=S.response;else{e=S.responseText;try{"script"==d?(1,eval)(e):"xml"==d?e=S.responseXML:"json"==d&&(e=T.test(e)?null:t.parseJSON(e))}catch(r){n=r}if(n)return a(n,"parsererror",S,u,p)}s(e,S,u,p)}else a(S.statusText||null,S.status?"error":"abort",S,u,p)}},o(S,u)===!1)return S.abort(),a(null,"abort",S,u,p),S;if(u.xhrFields)for(g in u.xhrFields)S[g]=u.xhrFields[g];var O="async"in u?u.async:!0;S.open(u.type,u.url,O,u.username,u.password);for(g in w)N.apply(S,w[g]);return u.timeout>0&&(b=setTimeout(function(){S.onreadystatechange=c,S.abort(),a(null,"timeout",S,u,p)},u.timeout)),S.send(u.data?u.data:null),S},t.get=function(){return t.ajax(p.apply(null,arguments))},t.post=function(){var e=p.apply(null,arguments);return e.type="POST",t.ajax(e)},t.getJSON=function(){var e=p.apply(null,arguments);return e.dataType="json",t.ajax(e)},t.fn.load=function(e,n,r){if(!this.length)return this;var i,o=this,s=e.split(/\s/),a=p(e,n,r),u=a.success;return s.length>1&&(a.url=s[0],i=s[1]),a.success=function(e){o.html(i?t("
").html(e.replace(b,"")).find(i):e),u&&u.apply(o,arguments)},t.ajax(a),this};var S=encodeURIComponent;t.param=function(e,n){var r=[];return r.add=function(e,n){t.isFunction(n)&&(n=n()),null==n&&(n=""),this.push(S(e)+"="+S(n))},d(r,e,n),r.join("&").replace(/%20/g,"+")}}(Zepto),function(t){t.Callbacks=function(e){e=t.extend({},e);var n,r,i,o,s,a,u=[],c=!e.once&&[],l=function(t){for(n=e.memory&&t,r=!0,a=o||0,o=0,s=u.length,i=!0;u&&s>a;++a)if(u[a].apply(t[0],t[1])===!1&&e.stopOnFalse){n=!1;break}i=!1,u&&(c?c.length&&l(c.shift()):n?u.length=0:f.disable())},f={add:function(){if(u){var r=u.length,a=function(n){t.each(n,function(t,n){"function"==typeof n?e.unique&&f.has(n)||u.push(n):n&&n.length&&"string"!=typeof n&&a(n)})};a(arguments),i?s=u.length:n&&(o=r,l(n))}return this},remove:function(){return u&&t.each(arguments,function(e,n){for(var r;(r=t.inArray(n,u,r))>-1;)u.splice(r,1),i&&(s>=r&&--s,a>=r&&--a)}),this},has:function(e){return!(!u||!(e?t.inArray(e,u)>-1:u.length))},empty:function(){return s=u.length=0,this},disable:function(){return u=c=n=void 0,this},disabled:function(){return!u},lock:function(){return c=void 0,n||f.disable(),this},locked:function(){return!c},fireWith:function(t,e){return!u||r&&!c||(e=e||[],e=[t,e.slice?e.slice():e],i?c.push(e):l(e)),this},fire:function(){return f.fireWith(this,arguments)},fired:function(){return!!r}};return f}}(Zepto),function(t){function e(n){var r=[["resolve","done",t.Callbacks({once:1,memory:1}),"resolved"],["reject","fail",t.Callbacks({once:1,memory:1}),"rejected"],["notify","progress",t.Callbacks({memory:1})]],i="pending",o={state:function(){return i},always:function(){return s.done(arguments).fail(arguments),this},then:function(){var n=arguments;return e(function(e){t.each(r,function(r,i){var a=t.isFunction(n[r])&&n[r];s[i[1]](function(){var n=a&&a.apply(this,arguments);if(n&&t.isFunction(n.promise))n.promise().done(e.resolve).fail(e.reject).progress(e.notify);else{var r=this===o?e.promise():this,s=a?[n]:arguments;e[i[0]+"With"](r,s)}})}),n=null}).promise()},promise:function(e){return null!=e?t.extend(e,o):o}},s={};return t.each(r,function(t,e){var n=e[2],a=e[3];o[e[1]]=n.add,a&&n.add(function(){i=a},r[1^t][2].disable,r[2][2].lock),s[e[0]]=function(){return s[e[0]+"With"](this===s?o:this,arguments),this},s[e[0]+"With"]=n.fireWith}),o.promise(s),n&&n.call(s,s),s}var n=Array.prototype.slice;t.when=function(r){var i,o,s,a=n.call(arguments),u=a.length,c=0,l=1!==u||r&&t.isFunction(r.promise)?u:0,f=1===l?r:e(),h=function(t,e,r){return function(o){e[t]=this,r[t]=arguments.length>1?n.call(arguments):o,r===i?f.notifyWith(e,r):--l||f.resolveWith(e,r)}};if(u>1)for(i=new Array(u),o=new Array(u),s=new Array(u);u>c;++c)a[c]&&t.isFunction(a[c].promise)?a[c].promise().done(h(c,s,a)).fail(f.reject).progress(h(c,o,i)):--l;return l||f.resolveWith(s,a),f.promise()},t.Deferred=e}(Zepto),function(t){function e(t){return t._zid||(t._zid=h++)}function n(t,n,o,s){if(n=r(n),n.ns)var a=i(n.ns);return(g[e(t)]||[]).filter(function(t){return t&&(!n.e||t.e==n.e)&&(!n.ns||a.test(t.ns))&&(!o||e(t.fn)===e(o))&&(!s||t.sel==s)})}function r(t){var e=(""+t).split(".");return{e:e[0],ns:e.slice(1).sort().join(" ")}}function i(t){return new RegExp("(?:^| )"+t.replace(" "," .* ?")+"(?: |$)")}function o(t,e){return t.del&&!y&&t.e in b||!!e}function s(t){return x[t]||y&&b[t]||t}function a(n,i,a,u,l,h,p){var d=e(n),m=g[d]||(g[d]=[]);i.split(/\s/).forEach(function(e){if("ready"==e)return t(document).ready(a);var i=r(e);i.fn=a,i.sel=l,i.e in x&&(a=function(e){var n=e.relatedTarget;return!n||n!==this&&!t.contains(this,n)?i.fn.apply(this,arguments):void 0}),i.del=h;var d=h||a;i.proxy=function(t){if(t=c(t),!t.isImmediatePropagationStopped()){t.data=u;var e=d.apply(n,t._args==f?[t]:[t].concat(t._args));return e===!1&&(t.preventDefault(),t.stopPropagation()),e}},i.i=m.length,m.push(i),"addEventListener"in n&&n.addEventListener(s(i.e),i.proxy,o(i,p))})}function u(t,r,i,a,u){var c=e(t);(r||"").split(/\s/).forEach(function(e){n(t,e,i,a).forEach(function(e){delete g[c][e.i],"removeEventListener"in t&&t.removeEventListener(s(e.e),e.proxy,o(e,u))})})}function c(e,n){return(n||!e.isDefaultPrevented)&&(n||(n=e),t.each(T,function(t,r){var i=n[t];e[t]=function(){return this[r]=w,i&&i.apply(n,arguments)},e[r]=E}),(n.defaultPrevented!==f?n.defaultPrevented:"returnValue"in n?n.returnValue===!1:n.getPreventDefault&&n.getPreventDefault())&&(e.isDefaultPrevented=w)),e}function l(t){var e,n={originalEvent:t};for(e in t)j.test(e)||t[e]===f||(n[e]=t[e]);return c(n,t)}var f,h=1,p=Array.prototype.slice,d=t.isFunction,m=function(t){return"string"==typeof t},g={},v={},y="onfocusin"in window,b={focus:"focusin",blur:"focusout"},x={mouseenter:"mouseover",mouseleave:"mouseout"};v.click=v.mousedown=v.mouseup=v.mousemove="MouseEvents",t.event={add:a,remove:u},t.proxy=function(n,r){var i=2 in arguments&&p.call(arguments,2);if(d(n)){var o=function(){return n.apply(r,i?i.concat(p.call(arguments)):arguments)};return o._zid=e(n),o}if(m(r))return i?(i.unshift(n[r],n),t.proxy.apply(null,i)):t.proxy(n[r],n);throw new TypeError("expected function")},t.fn.bind=function(t,e,n){return this.on(t,e,n)},t.fn.unbind=function(t,e){return this.off(t,e)},t.fn.one=function(t,e,n,r){return this.on(t,e,n,r,1)};var w=function(){return!0},E=function(){return!1},j=/^([A-Z]|returnValue$|layer[XY]$)/,T={preventDefault:"isDefaultPrevented",stopImmediatePropagation:"isImmediatePropagationStopped",stopPropagation:"isPropagationStopped"};t.fn.delegate=function(t,e,n){return this.on(e,t,n)},t.fn.undelegate=function(t,e,n){return this.off(e,t,n)},t.fn.live=function(e,n){return t(document.body).delegate(this.selector,e,n),this},t.fn.die=function(e,n){return t(document.body).undelegate(this.selector,e,n),this},t.fn.on=function(e,n,r,i,o){var s,c,h=this;return e&&!m(e)?(t.each(e,function(t,e){h.on(t,n,r,e,o)}),h):(m(n)||d(i)||i===!1||(i=r,r=n,n=f),(i===f||r===!1)&&(i=r,r=f),i===!1&&(i=E),h.each(function(f,h){o&&(s=function(t){return u(h,t.type,i),i.apply(this,arguments)}),n&&(c=function(e){var r,o=t(e.target).closest(n,h).get(0);return o&&o!==h?(r=t.extend(l(e),{currentTarget:o,liveFired:h}),(s||i).apply(o,[r].concat(p.call(arguments,1)))):void 0}),a(h,e,i,r,n,c||s)}))},t.fn.off=function(e,n,r){var i=this;return e&&!m(e)?(t.each(e,function(t,e){i.off(t,n,e)}),i):(m(n)||d(r)||r===!1||(r=n,n=f),r===!1&&(r=E),i.each(function(){u(this,e,r,n)}))},t.fn.trigger=function(e,n){return e=m(e)||t.isPlainObject(e)?t.Event(e):c(e),e._args=n,this.each(function(){e.type in b&&"function"==typeof this[e.type]?this[e.type]():"dispatchEvent"in this?this.dispatchEvent(e):t(this).triggerHandler(e,n)})},t.fn.triggerHandler=function(e,r){var i,o;return this.each(function(s,a){i=l(m(e)?t.Event(e):e),i._args=r,i.target=a,t.each(n(a,e.type||e),function(t,e){return o=e.proxy(i),i.isImmediatePropagationStopped()?!1:void 0})}),o},"focusin focusout focus blur load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select keydown keypress keyup error".split(" ").forEach(function(e){t.fn[e]=function(t){return 0 in arguments?this.bind(e,t):this.trigger(e)}}),t.Event=function(t,e){m(t)||(e=t,t=e.type);var n=document.createEvent(v[t]||"Events"),r=!0;if(e)for(var i in e)"bubbles"==i?r=!!e[i]:n[i]=e[i];return n.initEvent(t,r,!0),c(n)}}(Zepto),function(t){t.fn.serializeArray=function(){var e,n,r=[],i=function(t){return t.forEach?t.forEach(i):void r.push({name:e,value:t})};return this[0]&&t.each(this[0].elements,function(r,o){n=o.type,e=o.name,e&&"fieldset"!=o.nodeName.toLowerCase()&&!o.disabled&&"submit"!=n&&"reset"!=n&&"button"!=n&&"file"!=n&&("radio"!=n&&"checkbox"!=n||o.checked)&&i(t(o).val())}),r},t.fn.serialize=function(){var t=[];return this.serializeArray().forEach(function(e){t.push(encodeURIComponent(e.name)+"="+encodeURIComponent(e.value))}),t.join("&")},t.fn.submit=function(e){if(0 in arguments)this.bind("submit",e);else if(this.length){var n=t.Event("submit");this.eq(0).trigger(n),n.isDefaultPrevented()||this.get(0).submit()}return this}}(Zepto); --------------------------------------------------------------------------------