├── src ├── less │ ├── common.less │ ├── mixin.less │ ├── variable.less │ ├── index.less │ └── reset.less ├── de.json ├── images │ ├── Shapes.jpg │ ├── avatar.png │ └── article.jpeg ├── components │ ├── Header.vue │ ├── archive-list.vue │ └── article-list.vue ├── pages │ ├── tag-detail.vue │ ├── post.vue │ ├── archive.vue │ ├── tags.vue │ ├── index.vue │ └── about.vue ├── main.js ├── App.vue ├── route.js └── lib │ └── mock │ └── db.json ├── .gitignore ├── dist ├── favicon.ico ├── images │ ├── Shapes.jpg │ ├── avatar.png │ └── article.jpeg ├── template │ └── index.ejs ├── pages │ └── index.html ├── css │ └── style.css └── js │ ├── manifest.de.9dd8f964.js │ ├── manifest.en.b80e69d6.js │ └── app.de.caf524e6.js ├── server └── app.js ├── .babelrc ├── webpack.config.dev.js ├── webpack.config.prod.js ├── README.md ├── package.json └── webpack.config.base.js /src/less/common.less: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/less/mixin.less: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | npm-debug.log -------------------------------------------------------------------------------- /src/de.json: -------------------------------------------------------------------------------- 1 | { 2 | "Hello World": "Hallo Welt" 3 | } -------------------------------------------------------------------------------- /src/less/variable.less: -------------------------------------------------------------------------------- 1 | @js-tag: yellow; 2 | @html-tag: red; -------------------------------------------------------------------------------- /src/less/index.less: -------------------------------------------------------------------------------- 1 | @import './reset.less'; 2 | @import './common.less'; -------------------------------------------------------------------------------- /dist/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommanderXL/x-blog/HEAD/dist/favicon.ico -------------------------------------------------------------------------------- /dist/images/Shapes.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommanderXL/x-blog/HEAD/dist/images/Shapes.jpg -------------------------------------------------------------------------------- /dist/images/avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommanderXL/x-blog/HEAD/dist/images/avatar.png -------------------------------------------------------------------------------- /src/images/Shapes.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommanderXL/x-blog/HEAD/src/images/Shapes.jpg -------------------------------------------------------------------------------- /src/images/avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommanderXL/x-blog/HEAD/src/images/avatar.png -------------------------------------------------------------------------------- /dist/images/article.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommanderXL/x-blog/HEAD/dist/images/article.jpeg -------------------------------------------------------------------------------- /src/images/article.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommanderXL/x-blog/HEAD/src/images/article.jpeg -------------------------------------------------------------------------------- /server/app.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const express = require('express') 3 | 4 | 5 | const app = express(); 6 | 7 | app.use(express.static('public')) 8 | -------------------------------------------------------------------------------- /src/components/Header.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | [ 4 | "es2015", 5 | { 6 | "modules": false 7 | } 8 | ] 9 | ], 10 | "plugins": [ 11 | "syntax-dynamic-import", 12 | "transform-object-rest-spread" 13 | ] 14 | } -------------------------------------------------------------------------------- /src/pages/tag-detail.vue: -------------------------------------------------------------------------------- 1 | 6 | 12 | 13 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import App from './App'; 3 | import router from './route'; 4 | import axios from 'axios'; 5 | import './less/index'; 6 | 7 | 8 | Vue.config.debug = true; 9 | Vue.prototype.http = axios; 10 | 11 | const app = new Vue({ 12 | router, 13 | ...App 14 | }).$mount('#app'); 15 | -------------------------------------------------------------------------------- /dist/template/index.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | <%= htmlWebpackPlugin.options.title %> 5 | 6 | 7 | 8 | 9 |
10 | 11 |
12 | 13 | -------------------------------------------------------------------------------- /webpack.config.dev.js: -------------------------------------------------------------------------------- 1 | const merge = require('webpack-merge'); 2 | 3 | module.exports = merge(require('./webpack.config.base'), { 4 | devServer: { 5 | proxy: { 6 | '/api': { 7 | target: 'http://localhost:3001', 8 | changeOrigin: true, 9 | secure: false, 10 | pathRewrite: { 11 | "^/api": "" 12 | } 13 | } 14 | } 15 | } 16 | }) -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 16 | -------------------------------------------------------------------------------- /dist/pages/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | XRene Personal Blog 5 | 6 | 7 | 8 | 9 |
10 | 11 |
12 | 13 | -------------------------------------------------------------------------------- /src/pages/post.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 34 | 35 | -------------------------------------------------------------------------------- /src/route.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import Router from 'vue-router'; 3 | import IndexPage from './pages/index.vue'; 4 | import PostPage from './pages/post.vue'; 5 | import TagsPage from './pages/tags.vue'; 6 | import AboutPage from './pages/about.vue'; 7 | import ArchivePage from './pages/archive.vue'; 8 | import TagPage from './pages/tag-detail.vue'; 9 | 10 | Vue.use(Router); 11 | 12 | export default new Router({ 13 | routes: [{ 14 | path: '/', 15 | name: 'home', 16 | component: IndexPage 17 | }, 18 | { 19 | path: '/post', 20 | name: 'post', 21 | component: PostPage 22 | }, 23 | { 24 | path: '/tags', 25 | name: 'tags', 26 | component: TagsPage 27 | }, 28 | // 动态路由匹配, 以下的路由规则可以匹配 /tags/webpack | /tags/html 等路由 29 | // 然后用TagPage组件去进行页面的渲染 30 | { 31 | path: '/tags/:tag', 32 | name: 'tagDetail', 33 | component: TagPage 34 | }, 35 | { 36 | path: '/archive', 37 | name: 'archive', 38 | component: ArchivePage 39 | }, 40 | { 41 | path: '/about', 42 | name: 'about', 43 | component: AboutPage 44 | } 45 | ] 46 | }); -------------------------------------------------------------------------------- /src/less/reset.less: -------------------------------------------------------------------------------- 1 | html, body, div, span, applet, object, iframe, 2 | h1, h2, h3, h4, h5, h6, p, blockquote, pre, 3 | a, abbr, acronym, address, big, cite, code, 4 | del, dfn, em, img, ins, kbd, q, s, samp, 5 | small, strike, strong, sub, sup, tt, var, 6 | b, u, i, center, 7 | dl, dt, dd, ol, ul, li, 8 | fieldset, form, label, legend, 9 | table, caption, tbody, tfoot, thead, tr, th, td, 10 | article, aside, canvas, details, embed, 11 | figure, figcaption, footer, header, hgroup, 12 | main, menu, nav, output, ruby, section, summary, 13 | time, mark, audio, video { 14 | margin: 0; 15 | padding: 0; 16 | border: 0; 17 | font-size: 100%; 18 | font: inherit; 19 | vertical-align: baseline; 20 | } 21 | article, aside, details, figcaption, figure, 22 | footer, header, hgroup, main, menu, nav, section { 23 | display: block; 24 | } 25 | body { 26 | line-height: 1; 27 | } 28 | ol, ul { 29 | list-style: none; 30 | } 31 | blockquote, q { 32 | quotes: none; 33 | &:before, &:after { 34 | content: ''; 35 | content: none; 36 | } 37 | } 38 | table { 39 | border-collapse: collapse; 40 | border-spacing: 0; 41 | } 42 | a { 43 | text-decoration: none; 44 | &:hover, &:link, &:active, &:visited { 45 | color: #333; 46 | } 47 | } -------------------------------------------------------------------------------- /src/pages/archive.vue: -------------------------------------------------------------------------------- 1 | 13 | 36 | -------------------------------------------------------------------------------- /src/pages/tags.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 32 | 33 | -------------------------------------------------------------------------------- /webpack.config.prod.js: -------------------------------------------------------------------------------- 1 | const merge = require('webpack-merge'); 2 | const path = require('path'); 3 | const webpack = require('webpack'); 4 | const PATHS = { 5 | src: path.resolve(__dirname, './src'), 6 | dist: path.resolve(__dirname, './dist') 7 | }; 8 | const I18nPlugin = require('i18n-webpack-plugin'); 9 | const languages = { 10 | "en": null, 11 | "de": require('./src/de.json') 12 | } 13 | 14 | 15 | module.exports = Object.keys(languages).map(function(language) { 16 | return merge(require('./webpack.config.base'), { 17 | output: { 18 | path: PATHS.dist, 19 | publicPath: '/dist/', 20 | filename: `js/[name].${language}.[chunkhash:8].js`, // hash输出8位 21 | chunkFilename: `js/[name].${language}.[chunkhash:8].js`, 22 | }, 23 | devtool: false, 24 | plugins: [ 25 | /*new webpack.optimize.UglifyJsPlugin({ 26 | compress: { 27 | warnings: false, 28 | }, 29 | comments: false, 30 | except: ['exports', 'require'] //避免关键字被混淆 31 | }),*/ 32 | new I18nPlugin(languages[language]) 33 | ] 34 | }) 35 | }) 36 | 37 | /*module.exports = merge(require('./webpack.config.base'), { 38 | output: { 39 | path: PATHS.dist, 40 | publicPath: '/dist/', 41 | filename: `js/[name].[chunkhash:8].js`, // hash输出8位 42 | chunkFilename: `js/[name].[chunkhash:8].js`, 43 | }, 44 | devtool: false, 45 | plugins: [ 46 | new webpack.optimize.UglifyJsPlugin({ 47 | compress: { 48 | warnings: false, 49 | }, 50 | comments: false, 51 | except: ['exports', 'require'] //避免关键字被混淆 52 | }) 53 | ] 54 | })*/ -------------------------------------------------------------------------------- /src/pages/index.vue: -------------------------------------------------------------------------------- 1 | 17 | 24 | -------------------------------------------------------------------------------- /dist/css/style.css: -------------------------------------------------------------------------------- 1 | html, 2 | body, 3 | div, 4 | span, 5 | applet, 6 | object, 7 | iframe, 8 | h1, 9 | h2, 10 | h3, 11 | h4, 12 | h5, 13 | h6, 14 | p, 15 | blockquote, 16 | pre, 17 | a, 18 | abbr, 19 | acronym, 20 | address, 21 | big, 22 | cite, 23 | code, 24 | del, 25 | dfn, 26 | em, 27 | img, 28 | ins, 29 | kbd, 30 | q, 31 | s, 32 | samp, 33 | small, 34 | strike, 35 | strong, 36 | sub, 37 | sup, 38 | tt, 39 | var, 40 | b, 41 | u, 42 | i, 43 | center, 44 | dl, 45 | dt, 46 | dd, 47 | ol, 48 | ul, 49 | li, 50 | fieldset, 51 | form, 52 | label, 53 | legend, 54 | table, 55 | caption, 56 | tbody, 57 | tfoot, 58 | thead, 59 | tr, 60 | th, 61 | td, 62 | article, 63 | aside, 64 | canvas, 65 | details, 66 | embed, 67 | figure, 68 | figcaption, 69 | footer, 70 | header, 71 | hgroup, 72 | main, 73 | menu, 74 | nav, 75 | output, 76 | ruby, 77 | section, 78 | summary, 79 | time, 80 | mark, 81 | audio, 82 | video { 83 | margin: 0; 84 | padding: 0; 85 | border: 0; 86 | font-size: 100%; 87 | font: inherit; 88 | vertical-align: baseline; 89 | } 90 | article, 91 | aside, 92 | details, 93 | figcaption, 94 | figure, 95 | footer, 96 | header, 97 | hgroup, 98 | main, 99 | menu, 100 | nav, 101 | section { 102 | display: block; 103 | } 104 | body { 105 | line-height: 1; 106 | } 107 | ol, 108 | ul { 109 | list-style: none; 110 | } 111 | blockquote, 112 | q { 113 | quotes: none; 114 | } 115 | blockquote:before, 116 | q:before, 117 | blockquote:after, 118 | q:after { 119 | content: ''; 120 | content: none; 121 | } 122 | table { 123 | border-collapse: collapse; 124 | border-spacing: 0; 125 | } 126 | a { 127 | text-decoration: none; 128 | } 129 | a:hover, 130 | a:link, 131 | a:active, 132 | a:visited { 133 | color: #333; 134 | } 135 | -------------------------------------------------------------------------------- /src/components/archive-list.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 25 | 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## 个人博客 2 | 这是一个开源的个人`blog`项目.主要目的是玩一玩`vue`。大家可以在本项目中不仅仅可以学习了解以下的`框架/库`,同时还可以了解关于`代码结构组织`,`模块化`,`前端构建`等内容。这个项目才刚开始,我会带着大家完成整个`blog`项目的开发工作。 3 | 4 | ## 技术栈 5 | 6 | 前端 7 | * es6 8 | * vue2 9 | * webpack2 10 | * vue-router2 11 | * axios 12 | * less 13 | 14 | 后端 15 | * node 16 | * mongoDB 17 | 18 | 19 | ## 起手式 20 | 21 | ```javascript 22 | node -v 23 | v6.9.2 24 | 25 | npm -v 26 | 3.10.9 27 | ``` 28 | 29 | ```javascript 30 | 1. fork本项目 31 | 32 | 2. git clone ... 33 | 34 | 3. cd x-blog 35 | 36 | 4. npm install (建议使用淘宝镜像) 37 | 38 | 5. npm run dev 39 | 40 | 6. 浏览器打开 localhost:3000/pages 41 | ``` 42 | 43 | ## 交流 44 | 45 | * 有任何问题可以在这里提`issue` 46 | * 可以加入QQ群: 473540115. 暗号是: x-blog 47 | 48 | 49 | some tips: 50 | 51 | * 未接入后端前,前端使用`mock`数据 52 | 53 | ## 更新日志 54 | 55 | ### 2.14更新 56 | 57 | 完成`post`静态页面原型,修复`webpack`使用`extractTextPlugin`的正确姿势 58 | 59 | ### 2.15更新 60 | 61 | 添加`about`静态页面 62 | 63 | ### 2.16更新 64 | 65 | * 添加`json-server`. [使用方法请戳我](https://github.com/typicode/json-server) 66 | 67 | 主要作用就是在你开发环节在后端同学还未开发完成的情况下,提供一个`mock backend server`。 68 | 69 | 在我们还未开始写后端代码前,主要用这个`backend server`去模拟数据格式。 70 | 71 | PS: 因为你`webpack-dev-server`占用了一个端口,那么`json-server`需要使用另外一个端口。 72 | 这个时候需要利用`webpack-dev-server`提供的`proxy`功能。 73 | 74 | 具体的配置信息,见`webpack.config.dev.js`文件 75 | 76 | * 添加`axios`作为`http`资源库 77 | 78 | 其实`vue`对于开发者使用什么资源库没做什么限制。使用你顺手的就好了。 79 | 80 | 将`axios`集成进`vue`的方式见`App.vue`文件。 81 | 82 | [axios文档请戳我](https://github.com/mzabriskie/axios) 83 | 84 | [vue添加插件的方法请戳我](https://cn.vuejs.org/v2/guide/plugins.html) 85 | 86 | ### 2.18更新 87 | 88 | * 添加`webpack`生产环境配置信息 89 | 90 | 见`webpack.config.prod.js`文件。主要添加的内容为文件的`hash`,文件的打包及输出内容 91 | 92 | * `tags`页面添加`vue-router`路由动态匹配 93 | 94 | [使用方法请戳我](http://router.vuejs.org/zh-cn/essentials/dynamic-matching.html) 95 | 96 | ### 2.19更新 97 | 98 | * 添加mock数据, 见`lib/mock/db.json`文件 99 | * 完成`archive`静态页面 100 | 101 | 102 | ### 最近这2天有点忙,server端从周四开始更新,望大家理解 103 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "x-blog", 3 | "version": "1.0.0", 4 | "description": "person blog", 5 | "main": "index.js", 6 | "scripts": { 7 | "dev": "webpack-dashboard -- webpack-dev-server --config webpack.config.dev.js --compress true --devtool eval-source-map --progress --colors --hot --port 3000 --inline --host 0.0.0.0 --content-base ./dist", 8 | "server": "json-server --watch ./src/lib/mock/db.json --port 3001", 9 | "prod": "node ./build/build.js | webpack --config webpack.config.prod.js" 10 | }, 11 | "repository": { 12 | "type": "git", 13 | "url": "git+https://github.com/CommanderXL/x-blog.git" 14 | }, 15 | "keywords": [ 16 | "webpack2", 17 | "vue2", 18 | "node" 19 | ], 20 | "author": "XRene", 21 | "license": "ISC", 22 | "bugs": { 23 | "url": "https://github.com/CommanderXL/x-blog/issues" 24 | }, 25 | "homepage": "https://github.com/CommanderXL/x-blog#readme", 26 | "devDependencies": { 27 | "axios": "^0.15.3", 28 | "babel-core": "^6.22.1", 29 | "babel-loader": "^6.2.10", 30 | "babel-plugin-syntax-dynamic-import": "^6.18.0", 31 | "babel-plugin-transform-object-rest-spread": "^6.22.0", 32 | "babel-preset-es2015": "^6.22.0", 33 | "css-loader": "^0.26.1", 34 | "es6-promise": "^4.0.5", 35 | "extract-text-webpack-plugin": "^2.0.0-rc.3", 36 | "file-loader": "^0.10.0", 37 | "html-webpack-plugin": "^2.28.0", 38 | "i18n-loader": "^0.3.0", 39 | "i18n-webpack-plugin": "^0.3.0", 40 | "less": "^2.7.2", 41 | "less-loader": "^2.2.3", 42 | "open": "0.0.5", 43 | "opn": "^4.0.2", 44 | "pre-commit": "^1.2.2", 45 | "shelljs": "^0.7.6", 46 | "style-loader": "^0.13.1", 47 | "url-loader": "^0.5.7", 48 | "vue": "^2.1.10", 49 | "vue-i18n": "^6.0.0-alpha.2", 50 | "vue-loader": "^10.3.0", 51 | "vue-router": "^2.2.0", 52 | "vue-style-loader": "^2.0.0", 53 | "vue-template-compiler": "^2.1.10", 54 | "webpack": "^2.2.1", 55 | "webpack-dashboard": "^0.3.0", 56 | "webpack-dev-server": "^2.3.0", 57 | "webpack-merge": "^2.6.1" 58 | }, 59 | "dependencies": { 60 | "express": "^4.15.0" 61 | } 62 | } -------------------------------------------------------------------------------- /src/lib/mock/db.json: -------------------------------------------------------------------------------- 1 | { 2 | "posts": [ 3 | { "id": 1, "title": "json-server", "author": "typicode" } 4 | ], 5 | "comments": [ 6 | { "id": 1, "body": "some comment", "postId": 1 } 7 | ], 8 | "profile": { "name": "typicode" }, 9 | "archive": { 10 | "errno": 0, 11 | "errmsg": "dd", 12 | "data": [ 13 | { 14 | "time": "2017", 15 | "post_list": [ 16 | { 17 | "title": "没有Flexbox,但是我们还有table", 18 | "href": "", 19 | "time": "2-2" 20 | }, 21 | { 22 | "title": "没有Flexbox,但是我们还有table", 23 | "href": "", 24 | "time": "2-1" 25 | } 26 | ] 27 | }, 28 | { 29 | "time": "2016", 30 | "post_list": [ 31 | { 32 | "title": "webpack2分包及异步加载套路", 33 | "href": "", 34 | "time": "1-29" 35 | }, 36 | { 37 | "title": "webpack2分包及异步加载套路", 38 | "href": "", 39 | "time": "1-21" 40 | } 41 | ] 42 | } 43 | ] 44 | }, 45 | "tags": { 46 | "errno": 0, 47 | "errmsg": "xx", 48 | "data": [ 49 | { 50 | "text": "Js" 51 | }, 52 | { 53 | "text": "html" 54 | }, 55 | { 56 | "text": "Node.js" 57 | }, 58 | { 59 | "text": "webpack" 60 | }, 61 | { 62 | "text": "Css3" 63 | }, 64 | { 65 | "text": "网络安全" 66 | }, 67 | { 68 | "text": "linux" 69 | }, 70 | { 71 | "text": "Promise" 72 | } 73 | ] 74 | }, 75 | "post": { 76 | "errno": 0, 77 | "errmsg": "xxx", 78 | "data": [ 79 | { 80 | "time": "2017-2-13", 81 | "title": "webpack2分包及异步加载套路", 82 | "des": "大家快来围观呀", 83 | "tags": [ 84 | "JS", 85 | "HTML" 86 | ] 87 | }, 88 | { 89 | "time": "2017-2-13", 90 | "title": "webpack2分包及异步加载套路", 91 | "des": "大家快来围观呀", 92 | "tags": [ 93 | "JS", 94 | "HTML" 95 | ] 96 | }, 97 | { 98 | "time": "2017-2-13", 99 | "title": "webpack2分包及异步加载套路", 100 | "des": "大家快来围观呀", 101 | "tags": [ 102 | "JS", 103 | "HTML" 104 | ] 105 | } 106 | ] 107 | } 108 | } -------------------------------------------------------------------------------- /src/components/article-list.vue: -------------------------------------------------------------------------------- 1 | 28 | 38 | -------------------------------------------------------------------------------- /webpack.config.base.js: -------------------------------------------------------------------------------- 1 | const webpack = require('webpack'); 2 | const path = require("path"); 3 | const fs = require("fs"); 4 | const ExtractTextPlugin = require("extract-text-webpack-plugin"); 5 | const HtmlWebpackPlugin = require("html-webpack-plugin"); 6 | 7 | 8 | const PATHS = { 9 | src: path.resolve(__dirname, './src'), 10 | dist: path.resolve(__dirname, './dist') 11 | } 12 | 13 | module.exports = { 14 | entry: { 15 | app: './src/main.js', // 整个SPA的入口文件, 一切的文件依赖关系从它开始 16 | vendors: ['vue', 'vue-router'] // 需要进行单独打包的文件 17 | }, 18 | output: { 19 | path: PATHS.dist, 20 | filename: 'js/[name].js', 21 | publicPath: '/dist/', // 部署文件 相对于根路由 22 | chunkFilename: 'js/[name].js' // chunk文件输出的文件名称 具体格式见webpack文档, 注意区分 hash/chunkhash/contenthash 等内容, 以及存在的潜在的坑 23 | }, 24 | devtool: '#eval-source-map', // 开始source-map. 具体的不同配置信息见webpack文档 25 | module: { 26 | rules: [{ 27 | test: /\.vue$/, 28 | loader: 'vue-loader' 29 | }, 30 | { 31 | test: /\.js/, 32 | loader: 'babel-loader', 33 | exclude: /node_modules/ 34 | }, 35 | { 36 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, 37 | loader: 'url-loader?limit=10240&name=images/[name].[ext]' 38 | }, 39 | { 40 | test: /\.less/, 41 | use: ExtractTextPlugin.extract({ 42 | fallback: 'style-loader', 43 | use: [ 44 | 'css-loader', 45 | 'less-loader' 46 | ] 47 | }) 48 | }, 49 | { 50 | test: /\.css/, 51 | use: ExtractTextPlugin.extract({ 52 | fallback: 'style-loader', 53 | use: [ 54 | 'css-loader' 55 | ] 56 | }) 57 | } 58 | ] 59 | }, 60 | resolve: { 61 | alias: { 62 | 'vue$': 'vue/dist/vue.common.js', 63 | 'components': path.join(__dirname, 'src/components'), // 定义文件路径, 加速打包过程中webpack路径查找过程 64 | 'lib': path.join(__dirname, 'src/lib'), 65 | 'less': path.join(__dirname, 'src/less') 66 | }, 67 | extensions: ['.js', '.less', '.vue', '*', '.json'] // 可以不加后缀, 直接使用 import xx from 'xx' 的语法 68 | }, 69 | plugins: [ 70 | new HtmlWebpackPlugin({ // html模板输出插件 71 | title: 'XRene Personal Blog', 72 | template: `${PATHS.dist}/template/index.ejs`, 73 | inject: 'body', 74 | filename: `${PATHS.dist}/pages/index.html` 75 | }), 76 | new ExtractTextPlugin({ // css抽离插件,单独放到一个style文件当中. 77 | filename: `css/style.css`, 78 | allChunks: true, 79 | disable: false 80 | }), 81 | // 将vue等框架/库进行单独打包, 并输入到vendors.js文件当中 82 | // 这个地方commonChunkPlugin一共会输出2个文件, 第二个文件是webpack的runtime文件 83 | // runtime文件用以定义一些webpack提供的全局函数及需要异步加载的chunk文件 84 | // 具体的内容可以看我写的blog 85 | // [webpack分包及异步加载套路](https://segmentfault.com/a/1190000007962830) 86 | // [webpack2异步加载套路](https://segmentfault.com/a/1190000008279471) 87 | new webpack.optimize.CommonsChunkPlugin({ 88 | names: ['vendors', 'manifest'] 89 | }) 90 | ] 91 | } -------------------------------------------------------------------------------- /src/pages/about.vue: -------------------------------------------------------------------------------- 1 | 50 | 57 | -------------------------------------------------------------------------------- /dist/js/manifest.de.9dd8f964.js: -------------------------------------------------------------------------------- 1 | /******/ (function(modules) { // webpackBootstrap 2 | /******/ // install a JSONP callback for chunk loading 3 | /******/ var parentJsonpFunction = window["webpackJsonp"]; 4 | /******/ window["webpackJsonp"] = function webpackJsonpCallback(chunkIds, moreModules, executeModules) { 5 | /******/ // add "moreModules" to the modules object, 6 | /******/ // then flag all "chunkIds" as loaded and fire callback 7 | /******/ var moduleId, chunkId, i = 0, resolves = [], result; 8 | /******/ for(;i < chunkIds.length; i++) { 9 | /******/ chunkId = chunkIds[i]; 10 | /******/ if(installedChunks[chunkId]) 11 | /******/ resolves.push(installedChunks[chunkId][0]); 12 | /******/ installedChunks[chunkId] = 0; 13 | /******/ } 14 | /******/ for(moduleId in moreModules) { 15 | /******/ if(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) { 16 | /******/ modules[moduleId] = moreModules[moduleId]; 17 | /******/ } 18 | /******/ } 19 | /******/ if(parentJsonpFunction) parentJsonpFunction(chunkIds, moreModules, executeModules); 20 | /******/ while(resolves.length) 21 | /******/ resolves.shift()(); 22 | /******/ if(executeModules) { 23 | /******/ for(i=0; i < executeModules.length; i++) { 24 | /******/ result = __webpack_require__(__webpack_require__.s = executeModules[i]); 25 | /******/ } 26 | /******/ } 27 | /******/ return result; 28 | /******/ }; 29 | 30 | /******/ // The module cache 31 | /******/ var installedModules = {}; 32 | 33 | /******/ // objects to store loaded and loading chunks 34 | /******/ var installedChunks = { 35 | /******/ 2: 0 36 | /******/ }; 37 | 38 | /******/ // The require function 39 | /******/ function __webpack_require__(moduleId) { 40 | 41 | /******/ // Check if module is in cache 42 | /******/ if(installedModules[moduleId]) 43 | /******/ return installedModules[moduleId].exports; 44 | 45 | /******/ // Create a new module (and put it into the cache) 46 | /******/ var module = installedModules[moduleId] = { 47 | /******/ i: moduleId, 48 | /******/ l: false, 49 | /******/ exports: {} 50 | /******/ }; 51 | 52 | /******/ // Execute the module function 53 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); 54 | 55 | /******/ // Flag the module as loaded 56 | /******/ module.l = true; 57 | 58 | /******/ // Return the exports of the module 59 | /******/ return module.exports; 60 | /******/ } 61 | 62 | /******/ // This file contains only the entry chunk. 63 | /******/ // The chunk loading function for additional chunks 64 | /******/ __webpack_require__.e = function requireEnsure(chunkId) { 65 | /******/ if(installedChunks[chunkId] === 0) 66 | /******/ return Promise.resolve(); 67 | 68 | /******/ // an Promise means "currently loading". 69 | /******/ if(installedChunks[chunkId]) { 70 | /******/ return installedChunks[chunkId][2]; 71 | /******/ } 72 | /******/ // start chunk loading 73 | /******/ var head = document.getElementsByTagName('head')[0]; 74 | /******/ var script = document.createElement('script'); 75 | /******/ script.type = 'text/javascript'; 76 | /******/ script.charset = 'utf-8'; 77 | /******/ script.async = true; 78 | /******/ script.timeout = 120000; 79 | 80 | /******/ if (__webpack_require__.nc) { 81 | /******/ script.setAttribute("nonce", __webpack_require__.nc); 82 | /******/ } 83 | /******/ script.src = __webpack_require__.p + "js/" + ({"0":"app","1":"vendors"}[chunkId]||chunkId) + ".de." + {"0":"caf524e6","1":"7f798225"}[chunkId] + ".js"; 84 | /******/ var timeout = setTimeout(onScriptComplete, 120000); 85 | /******/ script.onerror = script.onload = onScriptComplete; 86 | /******/ function onScriptComplete() { 87 | /******/ // avoid mem leaks in IE. 88 | /******/ script.onerror = script.onload = null; 89 | /******/ clearTimeout(timeout); 90 | /******/ var chunk = installedChunks[chunkId]; 91 | /******/ if(chunk !== 0) { 92 | /******/ if(chunk) chunk[1](new Error('Loading chunk ' + chunkId + ' failed.')); 93 | /******/ installedChunks[chunkId] = undefined; 94 | /******/ } 95 | /******/ }; 96 | 97 | /******/ var promise = new Promise(function(resolve, reject) { 98 | /******/ installedChunks[chunkId] = [resolve, reject]; 99 | /******/ }); 100 | /******/ installedChunks[chunkId][2] = promise; 101 | 102 | /******/ head.appendChild(script); 103 | /******/ return promise; 104 | /******/ }; 105 | 106 | /******/ // expose the modules object (__webpack_modules__) 107 | /******/ __webpack_require__.m = modules; 108 | 109 | /******/ // expose the module cache 110 | /******/ __webpack_require__.c = installedModules; 111 | 112 | /******/ // identity function for calling harmony imports with the correct context 113 | /******/ __webpack_require__.i = function(value) { return value; }; 114 | 115 | /******/ // define getter function for harmony exports 116 | /******/ __webpack_require__.d = function(exports, name, getter) { 117 | /******/ if(!__webpack_require__.o(exports, name)) { 118 | /******/ Object.defineProperty(exports, name, { 119 | /******/ configurable: false, 120 | /******/ enumerable: true, 121 | /******/ get: getter 122 | /******/ }); 123 | /******/ } 124 | /******/ }; 125 | 126 | /******/ // getDefaultExport function for compatibility with non-harmony modules 127 | /******/ __webpack_require__.n = function(module) { 128 | /******/ var getter = module && module.__esModule ? 129 | /******/ function getDefault() { return module['default']; } : 130 | /******/ function getModuleExports() { return module; }; 131 | /******/ __webpack_require__.d(getter, 'a', getter); 132 | /******/ return getter; 133 | /******/ }; 134 | 135 | /******/ // Object.prototype.hasOwnProperty.call 136 | /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; 137 | 138 | /******/ // __webpack_public_path__ 139 | /******/ __webpack_require__.p = "/dist/"; 140 | 141 | /******/ // on error function for async loading 142 | /******/ __webpack_require__.oe = function(err) { console.error(err); throw err; }; 143 | /******/ }) 144 | /************************************************************************/ 145 | /******/ ([]); -------------------------------------------------------------------------------- /dist/js/manifest.en.b80e69d6.js: -------------------------------------------------------------------------------- 1 | /******/ (function(modules) { // webpackBootstrap 2 | /******/ // install a JSONP callback for chunk loading 3 | /******/ var parentJsonpFunction = window["webpackJsonp"]; 4 | /******/ window["webpackJsonp"] = function webpackJsonpCallback(chunkIds, moreModules, executeModules) { 5 | /******/ // add "moreModules" to the modules object, 6 | /******/ // then flag all "chunkIds" as loaded and fire callback 7 | /******/ var moduleId, chunkId, i = 0, resolves = [], result; 8 | /******/ for(;i < chunkIds.length; i++) { 9 | /******/ chunkId = chunkIds[i]; 10 | /******/ if(installedChunks[chunkId]) 11 | /******/ resolves.push(installedChunks[chunkId][0]); 12 | /******/ installedChunks[chunkId] = 0; 13 | /******/ } 14 | /******/ for(moduleId in moreModules) { 15 | /******/ if(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) { 16 | /******/ modules[moduleId] = moreModules[moduleId]; 17 | /******/ } 18 | /******/ } 19 | /******/ if(parentJsonpFunction) parentJsonpFunction(chunkIds, moreModules, executeModules); 20 | /******/ while(resolves.length) 21 | /******/ resolves.shift()(); 22 | /******/ if(executeModules) { 23 | /******/ for(i=0; i < executeModules.length; i++) { 24 | /******/ result = __webpack_require__(__webpack_require__.s = executeModules[i]); 25 | /******/ } 26 | /******/ } 27 | /******/ return result; 28 | /******/ }; 29 | 30 | /******/ // The module cache 31 | /******/ var installedModules = {}; 32 | 33 | /******/ // objects to store loaded and loading chunks 34 | /******/ var installedChunks = { 35 | /******/ 2: 0 36 | /******/ }; 37 | 38 | /******/ // The require function 39 | /******/ function __webpack_require__(moduleId) { 40 | 41 | /******/ // Check if module is in cache 42 | /******/ if(installedModules[moduleId]) 43 | /******/ return installedModules[moduleId].exports; 44 | 45 | /******/ // Create a new module (and put it into the cache) 46 | /******/ var module = installedModules[moduleId] = { 47 | /******/ i: moduleId, 48 | /******/ l: false, 49 | /******/ exports: {} 50 | /******/ }; 51 | 52 | /******/ // Execute the module function 53 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); 54 | 55 | /******/ // Flag the module as loaded 56 | /******/ module.l = true; 57 | 58 | /******/ // Return the exports of the module 59 | /******/ return module.exports; 60 | /******/ } 61 | 62 | /******/ // This file contains only the entry chunk. 63 | /******/ // The chunk loading function for additional chunks 64 | /******/ __webpack_require__.e = function requireEnsure(chunkId) { 65 | /******/ if(installedChunks[chunkId] === 0) 66 | /******/ return Promise.resolve(); 67 | 68 | /******/ // an Promise means "currently loading". 69 | /******/ if(installedChunks[chunkId]) { 70 | /******/ return installedChunks[chunkId][2]; 71 | /******/ } 72 | /******/ // start chunk loading 73 | /******/ var head = document.getElementsByTagName('head')[0]; 74 | /******/ var script = document.createElement('script'); 75 | /******/ script.type = 'text/javascript'; 76 | /******/ script.charset = 'utf-8'; 77 | /******/ script.async = true; 78 | /******/ script.timeout = 120000; 79 | 80 | /******/ if (__webpack_require__.nc) { 81 | /******/ script.setAttribute("nonce", __webpack_require__.nc); 82 | /******/ } 83 | /******/ script.src = __webpack_require__.p + "js/" + ({"0":"app","1":"vendors"}[chunkId]||chunkId) + ".en." + {"0":"b8451ebd","1":"7f798225"}[chunkId] + ".js"; 84 | /******/ var timeout = setTimeout(onScriptComplete, 120000); 85 | /******/ script.onerror = script.onload = onScriptComplete; 86 | /******/ function onScriptComplete() { 87 | /******/ // avoid mem leaks in IE. 88 | /******/ script.onerror = script.onload = null; 89 | /******/ clearTimeout(timeout); 90 | /******/ var chunk = installedChunks[chunkId]; 91 | /******/ if(chunk !== 0) { 92 | /******/ if(chunk) chunk[1](new Error('Loading chunk ' + chunkId + ' failed.')); 93 | /******/ installedChunks[chunkId] = undefined; 94 | /******/ } 95 | /******/ }; 96 | 97 | /******/ var promise = new Promise(function(resolve, reject) { 98 | /******/ installedChunks[chunkId] = [resolve, reject]; 99 | /******/ }); 100 | /******/ installedChunks[chunkId][2] = promise; 101 | 102 | /******/ head.appendChild(script); 103 | /******/ return promise; 104 | /******/ }; 105 | 106 | /******/ // expose the modules object (__webpack_modules__) 107 | /******/ __webpack_require__.m = modules; 108 | 109 | /******/ // expose the module cache 110 | /******/ __webpack_require__.c = installedModules; 111 | 112 | /******/ // identity function for calling harmony imports with the correct context 113 | /******/ __webpack_require__.i = function(value) { return value; }; 114 | 115 | /******/ // define getter function for harmony exports 116 | /******/ __webpack_require__.d = function(exports, name, getter) { 117 | /******/ if(!__webpack_require__.o(exports, name)) { 118 | /******/ Object.defineProperty(exports, name, { 119 | /******/ configurable: false, 120 | /******/ enumerable: true, 121 | /******/ get: getter 122 | /******/ }); 123 | /******/ } 124 | /******/ }; 125 | 126 | /******/ // getDefaultExport function for compatibility with non-harmony modules 127 | /******/ __webpack_require__.n = function(module) { 128 | /******/ var getter = module && module.__esModule ? 129 | /******/ function getDefault() { return module['default']; } : 130 | /******/ function getModuleExports() { return module; }; 131 | /******/ __webpack_require__.d(getter, 'a', getter); 132 | /******/ return getter; 133 | /******/ }; 134 | 135 | /******/ // Object.prototype.hasOwnProperty.call 136 | /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; 137 | 138 | /******/ // __webpack_public_path__ 139 | /******/ __webpack_require__.p = "/dist/"; 140 | 141 | /******/ // on error function for async loading 142 | /******/ __webpack_require__.oe = function(err) { console.error(err); throw err; }; 143 | /******/ }) 144 | /************************************************************************/ 145 | /******/ ([]); -------------------------------------------------------------------------------- /dist/js/app.de.caf524e6.js: -------------------------------------------------------------------------------- 1 | webpackJsonp([0,2],[ 2 | /* 0 */ 3 | /***/ (function(module, exports, __webpack_require__) { 4 | 5 | "use strict"; 6 | 7 | 8 | var bind = __webpack_require__(12); 9 | 10 | /*global toString:true*/ 11 | 12 | // utils is a library of generic helper functions non-specific to axios 13 | 14 | var toString = Object.prototype.toString; 15 | 16 | /** 17 | * Determine if a value is an Array 18 | * 19 | * @param {Object} val The value to test 20 | * @returns {boolean} True if value is an Array, otherwise false 21 | */ 22 | function isArray(val) { 23 | return toString.call(val) === '[object Array]'; 24 | } 25 | 26 | /** 27 | * Determine if a value is an ArrayBuffer 28 | * 29 | * @param {Object} val The value to test 30 | * @returns {boolean} True if value is an ArrayBuffer, otherwise false 31 | */ 32 | function isArrayBuffer(val) { 33 | return toString.call(val) === '[object ArrayBuffer]'; 34 | } 35 | 36 | /** 37 | * Determine if a value is a FormData 38 | * 39 | * @param {Object} val The value to test 40 | * @returns {boolean} True if value is an FormData, otherwise false 41 | */ 42 | function isFormData(val) { 43 | return (typeof FormData !== 'undefined') && (val instanceof FormData); 44 | } 45 | 46 | /** 47 | * Determine if a value is a view on an ArrayBuffer 48 | * 49 | * @param {Object} val The value to test 50 | * @returns {boolean} True if value is a view on an ArrayBuffer, otherwise false 51 | */ 52 | function isArrayBufferView(val) { 53 | var result; 54 | if ((typeof ArrayBuffer !== 'undefined') && (ArrayBuffer.isView)) { 55 | result = ArrayBuffer.isView(val); 56 | } else { 57 | result = (val) && (val.buffer) && (val.buffer instanceof ArrayBuffer); 58 | } 59 | return result; 60 | } 61 | 62 | /** 63 | * Determine if a value is a String 64 | * 65 | * @param {Object} val The value to test 66 | * @returns {boolean} True if value is a String, otherwise false 67 | */ 68 | function isString(val) { 69 | return typeof val === 'string'; 70 | } 71 | 72 | /** 73 | * Determine if a value is a Number 74 | * 75 | * @param {Object} val The value to test 76 | * @returns {boolean} True if value is a Number, otherwise false 77 | */ 78 | function isNumber(val) { 79 | return typeof val === 'number'; 80 | } 81 | 82 | /** 83 | * Determine if a value is undefined 84 | * 85 | * @param {Object} val The value to test 86 | * @returns {boolean} True if the value is undefined, otherwise false 87 | */ 88 | function isUndefined(val) { 89 | return typeof val === 'undefined'; 90 | } 91 | 92 | /** 93 | * Determine if a value is an Object 94 | * 95 | * @param {Object} val The value to test 96 | * @returns {boolean} True if value is an Object, otherwise false 97 | */ 98 | function isObject(val) { 99 | return val !== null && typeof val === 'object'; 100 | } 101 | 102 | /** 103 | * Determine if a value is a Date 104 | * 105 | * @param {Object} val The value to test 106 | * @returns {boolean} True if value is a Date, otherwise false 107 | */ 108 | function isDate(val) { 109 | return toString.call(val) === '[object Date]'; 110 | } 111 | 112 | /** 113 | * Determine if a value is a File 114 | * 115 | * @param {Object} val The value to test 116 | * @returns {boolean} True if value is a File, otherwise false 117 | */ 118 | function isFile(val) { 119 | return toString.call(val) === '[object File]'; 120 | } 121 | 122 | /** 123 | * Determine if a value is a Blob 124 | * 125 | * @param {Object} val The value to test 126 | * @returns {boolean} True if value is a Blob, otherwise false 127 | */ 128 | function isBlob(val) { 129 | return toString.call(val) === '[object Blob]'; 130 | } 131 | 132 | /** 133 | * Determine if a value is a Function 134 | * 135 | * @param {Object} val The value to test 136 | * @returns {boolean} True if value is a Function, otherwise false 137 | */ 138 | function isFunction(val) { 139 | return toString.call(val) === '[object Function]'; 140 | } 141 | 142 | /** 143 | * Determine if a value is a Stream 144 | * 145 | * @param {Object} val The value to test 146 | * @returns {boolean} True if value is a Stream, otherwise false 147 | */ 148 | function isStream(val) { 149 | return isObject(val) && isFunction(val.pipe); 150 | } 151 | 152 | /** 153 | * Determine if a value is a URLSearchParams object 154 | * 155 | * @param {Object} val The value to test 156 | * @returns {boolean} True if value is a URLSearchParams object, otherwise false 157 | */ 158 | function isURLSearchParams(val) { 159 | return typeof URLSearchParams !== 'undefined' && val instanceof URLSearchParams; 160 | } 161 | 162 | /** 163 | * Trim excess whitespace off the beginning and end of a string 164 | * 165 | * @param {String} str The String to trim 166 | * @returns {String} The String freed of excess whitespace 167 | */ 168 | function trim(str) { 169 | return str.replace(/^\s*/, '').replace(/\s*$/, ''); 170 | } 171 | 172 | /** 173 | * Determine if we're running in a standard browser environment 174 | * 175 | * This allows axios to run in a web worker, and react-native. 176 | * Both environments support XMLHttpRequest, but not fully standard globals. 177 | * 178 | * web workers: 179 | * typeof window -> undefined 180 | * typeof document -> undefined 181 | * 182 | * react-native: 183 | * typeof document.createElement -> undefined 184 | */ 185 | function isStandardBrowserEnv() { 186 | return ( 187 | typeof window !== 'undefined' && 188 | typeof document !== 'undefined' && 189 | typeof document.createElement === 'function' 190 | ); 191 | } 192 | 193 | /** 194 | * Iterate over an Array or an Object invoking a function for each item. 195 | * 196 | * If `obj` is an Array callback will be called passing 197 | * the value, index, and complete array for each item. 198 | * 199 | * If 'obj' is an Object callback will be called passing 200 | * the value, key, and complete object for each property. 201 | * 202 | * @param {Object|Array} obj The object to iterate 203 | * @param {Function} fn The callback to invoke for each item 204 | */ 205 | function forEach(obj, fn) { 206 | // Don't bother if no value provided 207 | if (obj === null || typeof obj === 'undefined') { 208 | return; 209 | } 210 | 211 | // Force an array if not already something iterable 212 | if (typeof obj !== 'object' && !isArray(obj)) { 213 | /*eslint no-param-reassign:0*/ 214 | obj = [obj]; 215 | } 216 | 217 | if (isArray(obj)) { 218 | // Iterate over array values 219 | for (var i = 0, l = obj.length; i < l; i++) { 220 | fn.call(null, obj[i], i, obj); 221 | } 222 | } else { 223 | // Iterate over object keys 224 | for (var key in obj) { 225 | if (Object.prototype.hasOwnProperty.call(obj, key)) { 226 | fn.call(null, obj[key], key, obj); 227 | } 228 | } 229 | } 230 | } 231 | 232 | /** 233 | * Accepts varargs expecting each argument to be an object, then 234 | * immutably merges the properties of each object and returns result. 235 | * 236 | * When multiple objects contain the same key the later object in 237 | * the arguments list will take precedence. 238 | * 239 | * Example: 240 | * 241 | * ```js 242 | * var result = merge({foo: 123}, {foo: 456}); 243 | * console.log(result.foo); // outputs 456 244 | * ``` 245 | * 246 | * @param {Object} obj1 Object to merge 247 | * @returns {Object} Result of all merge properties 248 | */ 249 | function merge(/* obj1, obj2, obj3, ... */) { 250 | var result = {}; 251 | function assignValue(val, key) { 252 | if (typeof result[key] === 'object' && typeof val === 'object') { 253 | result[key] = merge(result[key], val); 254 | } else { 255 | result[key] = val; 256 | } 257 | } 258 | 259 | for (var i = 0, l = arguments.length; i < l; i++) { 260 | forEach(arguments[i], assignValue); 261 | } 262 | return result; 263 | } 264 | 265 | /** 266 | * Extends object a by mutably adding to it the properties of object b. 267 | * 268 | * @param {Object} a The object to be extended 269 | * @param {Object} b The object to copy properties from 270 | * @param {Object} thisArg The object to bind function to 271 | * @return {Object} The resulting value of object a 272 | */ 273 | function extend(a, b, thisArg) { 274 | forEach(b, function assignValue(val, key) { 275 | if (thisArg && typeof val === 'function') { 276 | a[key] = bind(val, thisArg); 277 | } else { 278 | a[key] = val; 279 | } 280 | }); 281 | return a; 282 | } 283 | 284 | module.exports = { 285 | isArray: isArray, 286 | isArrayBuffer: isArrayBuffer, 287 | isFormData: isFormData, 288 | isArrayBufferView: isArrayBufferView, 289 | isString: isString, 290 | isNumber: isNumber, 291 | isObject: isObject, 292 | isUndefined: isUndefined, 293 | isDate: isDate, 294 | isFile: isFile, 295 | isBlob: isBlob, 296 | isFunction: isFunction, 297 | isStream: isStream, 298 | isURLSearchParams: isURLSearchParams, 299 | isStandardBrowserEnv: isStandardBrowserEnv, 300 | forEach: forEach, 301 | merge: merge, 302 | extend: extend, 303 | trim: trim 304 | }; 305 | 306 | 307 | /***/ }), 308 | /* 1 */ 309 | /***/ (function(module, exports) { 310 | 311 | /* 312 | MIT License http://www.opensource.org/licenses/mit-license.php 313 | Author Tobias Koppers @sokra 314 | */ 315 | // css base code, injected by the css-loader 316 | module.exports = function() { 317 | var list = []; 318 | 319 | // return the list of modules as css string 320 | list.toString = function toString() { 321 | var result = []; 322 | for(var i = 0; i < this.length; i++) { 323 | var item = this[i]; 324 | if(item[2]) { 325 | result.push("@media " + item[2] + "{" + item[1] + "}"); 326 | } else { 327 | result.push(item[1]); 328 | } 329 | } 330 | return result.join(""); 331 | }; 332 | 333 | // import a list of modules into the list 334 | list.i = function(modules, mediaQuery) { 335 | if(typeof modules === "string") 336 | modules = [[null, modules, ""]]; 337 | var alreadyImportedModules = {}; 338 | for(var i = 0; i < this.length; i++) { 339 | var id = this[i][0]; 340 | if(typeof id === "number") 341 | alreadyImportedModules[id] = true; 342 | } 343 | for(i = 0; i < modules.length; i++) { 344 | var item = modules[i]; 345 | // skip already imported module 346 | // this implementation is not 100% perfect for weird media query combinations 347 | // when a module is imported multiple times with different media queries. 348 | // I hope this will never occur (Hey this way we have smaller bundles) 349 | if(typeof item[0] !== "number" || !alreadyImportedModules[item[0]]) { 350 | if(mediaQuery && !item[2]) { 351 | item[2] = mediaQuery; 352 | } else if(mediaQuery) { 353 | item[2] = "(" + item[2] + ") and (" + mediaQuery + ")"; 354 | } 355 | list.push(item); 356 | } 357 | } 358 | }; 359 | return list; 360 | }; 361 | 362 | 363 | /***/ }), 364 | /* 2 */ 365 | /***/ (function(module, exports) { 366 | 367 | module.exports = function normalizeComponent ( 368 | rawScriptExports, 369 | compiledTemplate, 370 | scopeId, 371 | cssModules 372 | ) { 373 | var esModule 374 | var scriptExports = rawScriptExports = rawScriptExports || {} 375 | 376 | // ES6 modules interop 377 | var type = typeof rawScriptExports.default 378 | if (type === 'object' || type === 'function') { 379 | esModule = rawScriptExports 380 | scriptExports = rawScriptExports.default 381 | } 382 | 383 | // Vue.extend constructor export interop 384 | var options = typeof scriptExports === 'function' 385 | ? scriptExports.options 386 | : scriptExports 387 | 388 | // render functions 389 | if (compiledTemplate) { 390 | options.render = compiledTemplate.render 391 | options.staticRenderFns = compiledTemplate.staticRenderFns 392 | } 393 | 394 | // scopedId 395 | if (scopeId) { 396 | options._scopeId = scopeId 397 | } 398 | 399 | // inject cssModules 400 | if (cssModules) { 401 | var computed = options.computed || (options.computed = {}) 402 | Object.keys(cssModules).forEach(function (key) { 403 | var module = cssModules[key] 404 | computed[key] = function () { return module } 405 | }) 406 | } 407 | 408 | return { 409 | esModule: esModule, 410 | exports: scriptExports, 411 | options: options 412 | } 413 | } 414 | 415 | 416 | /***/ }), 417 | /* 3 */ 418 | /***/ (function(module, exports, __webpack_require__) { 419 | 420 | /* 421 | MIT License http://www.opensource.org/licenses/mit-license.php 422 | Author Tobias Koppers @sokra 423 | Modified by Evan You @yyx990803 424 | */ 425 | 426 | var hasDocument = typeof document !== 'undefined' 427 | 428 | if (typeof DEBUG !== 'undefined' && DEBUG) { 429 | if (!hasDocument) { 430 | throw new Error( 431 | 'vue-style-loader cannot be used in a non-browser environment. ' + 432 | "Use { target: 'node' } in your Webpack config to indicate a server-rendering environment." 433 | ) } 434 | } 435 | 436 | var listToStyles = __webpack_require__(81) 437 | 438 | /* 439 | type StyleObject = { 440 | id: number; 441 | parts: Array 442 | } 443 | 444 | type StyleObjectPart = { 445 | css: string; 446 | media: string; 447 | sourceMap: ?string 448 | } 449 | */ 450 | 451 | var stylesInDom = {/* 452 | [id: number]: { 453 | id: number, 454 | refs: number, 455 | parts: Array<(obj?: StyleObjectPart) => void> 456 | } 457 | */} 458 | 459 | var head = hasDocument && (document.head || document.getElementsByTagName('head')[0]) 460 | var singletonElement = null 461 | var singletonCounter = 0 462 | var isProduction = false 463 | var noop = function () {} 464 | 465 | // Force single-tag solution on IE6-9, which has a hard limit on the # of