├── .babelrc ├── .editorconfig ├── .fecsignore ├── .fecsrc ├── .gitignore ├── LICENSE ├── README.md ├── build ├── build.js ├── rollup │ ├── alias.js │ ├── build.js │ └── rollup.config.js ├── webpack.config.base.js ├── webpack.config.dev.js └── webpack.config.prod.js ├── deps ├── README.md ├── fetch.js └── zepto.js ├── docs ├── .gitkeep ├── assets │ ├── intro-view-layer-element.jpg │ └── mip2-component-lifecycle.png ├── basic │ ├── announcement.md │ ├── demo.md │ ├── introduction.md │ ├── meta.json │ ├── mip-cache.md │ └── principle-of-mip.md ├── cli │ ├── cli-usage.md │ ├── component-development.md │ ├── component-testing.md │ ├── contribute-to-official-repo.md │ └── start-writing-first-mip.md ├── components │ ├── builtin │ │ ├── mip-bind.md │ │ ├── mip-carousel.md │ │ ├── mip-iframe.md │ │ ├── mip-img.md │ │ ├── mip-pix.md │ │ └── mip-video.md │ ├── components-list.md │ ├── data-and-method.md │ ├── extensions │ │ ├── mip-access.md │ │ ├── mip-accordion.md │ │ ├── mip-analytics.md │ │ ├── mip-anim.md │ │ ├── mip-app-banner.md │ │ ├── mip-appdl.md │ │ ├── mip-audio.md │ │ ├── mip-bind.md │ │ ├── mip-custom.md │ │ ├── mip-experiment.md │ │ ├── mip-filter.md │ │ ├── mip-fixed.md │ │ ├── mip-form.md │ │ ├── mip-gototop.md │ │ ├── mip-history.md │ │ ├── mip-html-os.md │ │ ├── mip-infinitescroll.md │ │ ├── mip-install-serviceworker.md │ │ ├── mip-lightbox.md │ │ ├── mip-link.md │ │ ├── mip-list.md │ │ ├── mip-login-done.md │ │ ├── mip-map.md │ │ ├── mip-mustache.md │ │ ├── mip-nav-slidedown.md │ │ ├── mip-sample.md │ │ ├── mip-scrollbox.md │ │ ├── mip-semi-fixed.md │ │ ├── mip-share.md │ │ ├── mip-showmore.md │ │ ├── mip-sidebar.md │ │ ├── mip-stats-baidu.md │ │ ├── mip-stats-cnzz.md │ │ ├── mip-stats-tianrun.md │ │ ├── mip-story.md │ │ ├── mip-toggle.md │ │ ├── mip-vd-baidu.md │ │ └── mip-vd-tabs.md │ ├── instance-life-cycle.md │ ├── introduction.md │ ├── layout.md │ ├── meta.json │ ├── mip-ad │ │ ├── mip-ad-baidu.md │ │ ├── mip-ad-baidussp.md │ │ ├── mip-ad-comm.md │ │ ├── mip-ad-imageplus.md │ │ ├── mip-ad-qwang.md │ │ ├── mip-ad-ssp.md │ │ ├── mip-ad.md │ │ └── mip-baidu-wm-ext.md │ └── syntax.md ├── page │ └── index.md ├── specs │ ├── mip-cache-spec.md │ ├── mip-components-spec.md │ ├── mip-html-spec.md │ └── mip-validate.md └── util │ └── sandbox.md ├── examples ├── builtin │ └── README.md ├── douban │ └── index.html ├── event │ ├── index.html │ ├── mip-a.js │ └── mip-b.js ├── lavas │ ├── extensions │ │ ├── mip-fixed │ │ │ ├── mip-fixed.js │ │ │ └── viewport-scroll.js │ │ ├── mip-nav-slidedown.js │ │ └── mip-sidebar.js │ ├── guide.html │ └── index.html ├── lifecycle │ ├── data.json │ ├── index.html │ └── mip-list.js ├── mip-bind │ ├── bind.html │ └── index.html ├── mip-extensions │ ├── README.md │ ├── mip-ad.js │ ├── mip-app-banner.js │ ├── mip-cambrian.js │ ├── mip-lightbox.js │ ├── mip-sidebar.js │ └── mip-stats-baidu.js ├── mip │ ├── index.html │ ├── list.html │ ├── mip-bind.js │ ├── mip-carousel.html │ ├── mip-iframe.html │ ├── mip-img.html │ ├── mip-list.js │ ├── mip-tree.js │ ├── mip-video.html │ ├── props.html │ ├── template.html │ └── tree.html ├── mip1 │ ├── doc │ │ └── 00-mip-101.html │ └── index.html ├── page │ ├── components │ │ ├── mip-complevel1.js │ │ ├── mip-complevel2.js │ │ └── mip-tree.js │ ├── data.html │ ├── data │ │ └── testData.json │ ├── index.html │ ├── not-mip.html │ └── tree.html ├── sandbox │ ├── index.html │ └── index.js ├── server.js ├── server.rollup.js ├── simple │ ├── index.html │ ├── mip-slide.js │ ├── mip-tree.js │ └── storeData.js ├── ssr │ └── index.html ├── static │ └── fonts │ │ ├── MaterialIcons-Regular.570eb838.woff2 │ │ ├── fontawesome-webfont.97493d3f.woff2 │ │ └── fontawesome-webfont.woff2 ├── store │ ├── components │ │ ├── mip-contacts.js │ │ ├── mip-hello.js │ │ ├── mip-init.js │ │ └── mip-store.js │ ├── index.html │ ├── storeData.js │ ├── testdata.json │ └── testdata2.json └── wecoffee │ ├── common.css │ ├── component.js │ ├── index.html │ └── rt-view.css ├── package.json └── src ├── components ├── index.js ├── mip-bind │ ├── bind.js │ ├── compile.js │ ├── deps.js │ ├── mip-data.js │ ├── observer.js │ └── watcher.js ├── mip-carousel.js ├── mip-iframe.js ├── mip-img.js ├── mip-pix.js └── mip-video.js ├── custom-element.js ├── fixed-element.js ├── index.js ├── layout.js ├── log ├── coreTags.js ├── logSend.js └── monitor.js ├── mip1-polyfill ├── customElement.js ├── element.js ├── index.js └── naboo.js ├── page ├── appshell │ ├── header.js │ ├── index.js │ └── loading.js ├── const │ └── index.js ├── create-router.js ├── index.js ├── router │ ├── history.js │ ├── index.js │ └── matcher.js └── util │ ├── dom.js │ ├── index.js │ ├── link.js │ ├── path.js │ ├── push-state.js │ ├── query.js │ ├── route.js │ ├── scroll-behavior.js │ ├── transition.js │ └── url.js ├── performance.js ├── polyfills ├── array-includes.js ├── babel-runtime-helpers.js ├── index.js ├── object-assign.js └── promise.js ├── register-element.js ├── resources.js ├── sandbox.js ├── sleepWakeModule.js ├── styles ├── fonts │ ├── MaterialIcons-Regular.ttf │ ├── MaterialIcons-Regular.woff │ └── MaterialIcons-Regular.woff2 ├── material-icons.css ├── mip-base.less ├── mip-carousel.less ├── mip-fixed.less ├── mip-html.less ├── mip-iframe.less ├── mip-img.less ├── mip-page.less ├── mip-text.less ├── mip-video.less ├── mip.less ├── mixin.less └── variable.less ├── util ├── customStorage.js ├── dom │ ├── css-loader.js │ ├── css.js │ ├── dom.js │ ├── event.js │ └── rect.js ├── event-action.js ├── event-emitter.js ├── fn.js ├── gesture │ ├── data-processor.js │ ├── gesture-recognizer.js │ └── index.js ├── hash.js ├── index.js ├── platform.js └── templates.js ├── viewer.js ├── viewport.js ├── vue-custom-element ├── index.js └── utils │ ├── create-vue-instance.js │ ├── custom-event.js │ ├── helpers.js │ ├── props.js │ └── slots.js └── vue ├── compiler ├── codegen │ ├── events.js │ └── index.js ├── create-compiler.js ├── directives │ ├── bind.js │ ├── index.js │ ├── model.js │ └── on.js ├── error-detector.js ├── helpers.js ├── index.js ├── optimizer.js ├── parser │ ├── entity-decoder.js │ ├── filter-parser.js │ ├── html-parser.js │ ├── index.js │ └── text-parser.js └── to-function.js ├── core ├── components │ ├── index.js │ └── keep-alive.js ├── config.js ├── global-api │ ├── assets.js │ ├── extend.js │ ├── index.js │ ├── mixin.js │ └── use.js ├── index.js ├── instance │ ├── events.js │ ├── index.js │ ├── init.js │ ├── inject.js │ ├── lifecycle.js │ ├── proxy.js │ ├── render-helpers │ │ ├── bind-object-listeners.js │ │ ├── bind-object-props.js │ │ ├── check-keycodes.js │ │ ├── index.js │ │ ├── render-list.js │ │ ├── render-slot.js │ │ ├── render-static.js │ │ ├── resolve-filter.js │ │ └── resolve-slots.js │ ├── render.js │ └── state.js ├── observer │ ├── array.js │ ├── dep.js │ ├── index.js │ ├── scheduler.js │ └── watcher.js ├── util │ ├── debug.js │ ├── env.js │ ├── error.js │ ├── index.js │ ├── lang.js │ ├── options.js │ ├── perf.js │ └── props.js └── vdom │ ├── create-component.js │ ├── create-element.js │ ├── create-functional-component.js │ ├── helpers │ ├── extract-props.js │ ├── get-first-component-child.js │ ├── index.js │ ├── is-async-placeholder.js │ ├── merge-hook.js │ ├── normalize-children.js │ ├── resolve-async-component.js │ └── update-listeners.js │ ├── modules │ ├── directives.js │ ├── index.js │ └── ref.js │ ├── patch.js │ └── vnode.js ├── platforms └── web │ ├── compiler │ ├── directives │ │ ├── html.js │ │ ├── index.js │ │ ├── model.js │ │ └── text.js │ ├── index.js │ ├── modules │ │ ├── class.js │ │ ├── index.js │ │ ├── model.js │ │ └── style.js │ ├── options.js │ └── util.js │ ├── entry-runtime-with-compiler.js │ ├── entry-runtime.js │ ├── runtime │ ├── class-util.js │ ├── components │ │ ├── index.js │ │ ├── transition-group.js │ │ └── transition.js │ ├── directives │ │ ├── index.js │ │ ├── model.js │ │ └── show.js │ ├── index.js │ ├── modules │ │ ├── attrs.js │ │ ├── class.js │ │ ├── dom-props.js │ │ ├── events.js │ │ ├── index.js │ │ ├── style.js │ │ └── transition.js │ ├── node-ops.js │ ├── patch.js │ └── transition-util.js │ └── util │ ├── attrs.js │ ├── class.js │ ├── compat.js │ ├── element.js │ ├── index.js │ └── style.js └── shared ├── constants.js └── util.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | [ 4 | "env", { 5 | "modules": false 6 | } 7 | ], 8 | "vue" 9 | ], 10 | "plugins": [ 11 | "transform-custom-element-classes", 12 | "syntax-dynamic-import", 13 | "transform-object-rest-spread", 14 | [ 15 | "transform-runtime", 16 | { 17 | "helpers": false, 18 | "polyfill": false, 19 | "regenerator": true 20 | } 21 | ] 22 | ], 23 | "ignore": [ 24 | "dist/*.js" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | UTF-8 2 | # This file is for unifying the coding style for different editors and IDEs 3 | # editorconfig.org 4 | root = true 5 | [*] 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | [*.{js,styl,html,json}] 11 | indent_size = 4 12 | indent_style = space 13 | [*.md] 14 | trim_trailing_whitespace = false 15 | -------------------------------------------------------------------------------- /.fecsignore: -------------------------------------------------------------------------------- 1 | src/page 2 | src/vue 3 | src/vuex 4 | src/router 5 | deps 6 | build 7 | dist 8 | examples 9 | node_modules 10 | -------------------------------------------------------------------------------- /.fecsrc: -------------------------------------------------------------------------------- 1 | { 2 | "eslint": { 3 | "env": { 4 | "node": true, 5 | "browser": true 6 | }, 7 | 8 | "globals": { 9 | "console": true, 10 | "require": true, 11 | "define": true 12 | }, 13 | 14 | "rules": { 15 | "no-console": 0, 16 | "brace-style": [2, "1tabs"], 17 | "fecs-no-require": "off", 18 | "fecs-prefer-async-await": "off", 19 | "fecs-one-var-per-line": "off", 20 | "prefer-rest-params": "off", 21 | "guard-for-in": "off", 22 | "fecs-export-on-declare": "off", 23 | "fecs-use-for-of": "off", 24 | "fecs-prefer-class": "off", 25 | "fecs-prefer-destructure": "off", 26 | "fecs-prefer-assign-pattern": "off", 27 | "fecs-use-computed-property": "off", 28 | "fecs-valid-map-set": "off" 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | *.log 4 | dist 5 | .vscode 6 | package-lock.json 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018-present mip-project 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | MIP 2 | 3 | ## 开发 4 | 5 | - Node.js v6+ 6 | - Clone 代码之后运行 7 | 8 | ```sh 9 | $ cnpm install # npm install 10 | ``` 11 | 12 | ## 常用命令 13 | 14 | ```sh 15 | # watch and auto re-build dist/mip.js 16 | $ npm run dev 17 | ``` 18 | 监控代码改动并编译代码到 `dist/mip.js`,可通过 `open examples/simple/index.html` 预览效果 19 | 20 | ```sh 21 | # build all dist files, including npm packages 22 | $ npm run build 23 | ``` 24 | 编译代码到 dist 目录 25 | -------------------------------------------------------------------------------- /build/build.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file webpack build 脚本 3 | * @author wangyisheng@baidu.com (wangyisheng) 4 | */ 5 | 6 | 'use strict'; 7 | 8 | process.env.NODE_ENV = 'production'; 9 | 10 | const ora = require('ora'); 11 | const rm = require('rimraf'); 12 | const path = require('path'); 13 | const chalk = require('chalk'); 14 | const webpack = require('webpack'); 15 | const webpackConfig = require('./webpack.config.prod'); 16 | 17 | const spinner = ora('building for production...'); 18 | spinner.start(); 19 | 20 | rm(path.join(__dirname, '../dist'), err => { 21 | if (err) { 22 | throw err; 23 | } 24 | 25 | webpack(webpackConfig, (err, stats) => { 26 | spinner.stop(); 27 | if (err) { 28 | throw err; 29 | } 30 | 31 | process.stdout.write(stats.toString({ 32 | colors: true, 33 | modules: false, 34 | children: false, // If you are using ts-loader, setting this to true will make TypeScript errors show up during build. 35 | chunks: false, 36 | chunkModules: false 37 | }) + '\n\n'); 38 | 39 | if (stats.hasErrors()) { 40 | console.log(chalk.red(' Build failed with errors.\n')); 41 | process.exit(1); 42 | } 43 | 44 | console.log(chalk.cyan(' Build complete.\n')); 45 | }); 46 | }); 47 | -------------------------------------------------------------------------------- /build/rollup/alias.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file alias.js 3 | * @author huanghuiquan (huanghuiquan@baidu.com) 4 | */ 5 | 6 | const path = require('path'); 7 | 8 | const resolve = p => path.resolve(__dirname, '../', p); 9 | 10 | module.exports = { 11 | vue: resolve('src/vue/platforms/web/entry-runtime'), 12 | compiler: resolve('src/vue/compiler'), 13 | core: resolve('src/vue/core'), 14 | shared: resolve('src/vue/shared'), 15 | web: resolve('src/vue/platforms/web'), 16 | // server: resolve('src/server'), 17 | // entries: resolve('src/entries'), 18 | sfc: resolve('src/vue/sfc'), 19 | deps: resolve('deps') 20 | }; 21 | -------------------------------------------------------------------------------- /build/webpack.config.dev.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file webpack dev 配置 3 | * @author wangyisheng@baidu.com (wangyisheng) 4 | */ 5 | 6 | const path = require('path'); 7 | const merge = require('webpack-merge'); 8 | const baseConfig = require('./webpack.config.base'); 9 | 10 | const resolve = p => path.resolve(__dirname, '../', p); 11 | 12 | module.exports = merge.smart(baseConfig, { 13 | mode: 'development', 14 | devtool: 'inline-source-map', 15 | entry: resolve('src/index.js'), 16 | resolve: { 17 | alias: { 18 | vue: resolve('src/vue/platforms/web/entry-runtime-with-compiler') 19 | } 20 | } 21 | }); 22 | -------------------------------------------------------------------------------- /build/webpack.config.prod.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file webpack prod 配置 3 | * @author wangyisheng@baidu.com (wangyisheng) 4 | */ 5 | 6 | const path = require('path'); 7 | const merge = require('webpack-merge'); 8 | const baseConfig = require('./webpack.config.base'); 9 | const MiniCssExtractPlugin = require('mini-css-extract-plugin'); 10 | const UglifyJsPlugin = require('uglifyjs-webpack-plugin'); 11 | const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; 12 | 13 | const resolve = p => path.resolve(__dirname, '../', p); 14 | 15 | module.exports = merge.smart(baseConfig, { 16 | mode: 'production', 17 | entry: resolve('src/index.js'), 18 | 19 | module: { 20 | rules: [] 21 | }, 22 | 23 | plugins: [ 24 | new MiniCssExtractPlugin({filename: 'mip.css'}), 25 | new UglifyJsPlugin(), 26 | new BundleAnalyzerPlugin() 27 | ] 28 | }); 29 | -------------------------------------------------------------------------------- /deps/README.md: -------------------------------------------------------------------------------- 1 | # deps 目录说明 2 | 3 | deps 目录均为第三方引用的 lib 4 | 5 | 有些 lib 有一些业务上的修改无法兼容,因此直接将源代码拷贝至此,而非通过 npm 来管理 6 | 7 | ## fetch 8 | 9 | 源文件:https://github.com/github/fetch/blob/master/fetch.js 10 | 11 | 主要修改点在于增加了 QQ 浏览器的判断,因为 QQ 浏览器的早起版本 fetch 实现有问题,发送请求会漏掉 cookie,因为在 QQ 浏览器中也通过 polyfill 的方式覆盖 fetch 12 | -------------------------------------------------------------------------------- /docs/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mip-project/mip/c88a032bb319095b515b73a1bef271e09d476d17/docs/.gitkeep -------------------------------------------------------------------------------- /docs/assets/intro-view-layer-element.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mip-project/mip/c88a032bb319095b515b73a1bef271e09d476d17/docs/assets/intro-view-layer-element.jpg -------------------------------------------------------------------------------- /docs/assets/mip2-component-lifecycle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mip-project/mip/c88a032bb319095b515b73a1bef271e09d476d17/docs/assets/mip2-component-lifecycle.png -------------------------------------------------------------------------------- /docs/basic/announcement.md: -------------------------------------------------------------------------------- 1 | # MIP 内容声明 2 | 3 | **从搜索结果页点出的MIP页面,其页面上的任何内容(包括但不限于广告、在线咨询、统计等组件)均视为在原站点上的投放和使用。** 4 | 5 | MIP(Mobile Instant Pages - 移动网页加速器), 是一套应用于移动网页的开放性技术标准。通过提供 MIP-HTML 规范、MIP-JS 运行环境以及 MIP-Cache 页面缓存系统,实现移动网页加速。 6 | 7 | 移动站点可以根据需要使用 MIP 技术进行开发,从而达到移动页面加速效果。 8 | 9 | 1. 站点发布的 MIP 页面,由站点开发人员采用 MIP 技术自行开发。开发与发布过程完全由站点把控。 10 | 2. 采用 MIP 技术开发的移动端页面,页面中展现的内容和功能,与普通移动端页面一样,完全由开发方放置。 11 | 3. 采用 MIP 技术开发的移动端页面,站点流量以及所投放广告等内容的展现与点击等使用情况,完全由开发方进行统计和监控。 12 | 4. 在用户使用搜索引擎时,为了保证 MIP 页面的加速效果,搜索引擎可能会将 MIP 页面缓存到离用户更近的 CDN 服务器。目前,缓存刷新的平均时间为50分钟左右。 13 | 14 | 因此,无论是从搜索点出的MIP页面还是直接访问的 MIP 页面,页面开发过程、展现内容、相关监控,均完全由站点开发方进行把控。在这两种情况下的页面上的任何内容(包括但不限于:广告、在线咨询、统计等组件)均视为在原站点上的投放和使用。 15 | -------------------------------------------------------------------------------- /docs/basic/introduction.md: -------------------------------------------------------------------------------- 1 | # 什么是 MIP 2 | 3 | MIP(Mobile Instant Pages - 移动网页加速器),是一套应用于移动网页的开放性技术标准。通过提供 MIP-HTML 规范、MIP-JS 运行环境以及 MIP-Cache 页面缓存系统,实现移动网页加速。 4 | 5 | MIP 主要由三部分组织成: 6 | 7 | - MIP-HTML:基于 HTML 中的基础标签制定了全新的规范,通过对一部分基础标签的使用限制或功能扩展,使 HTML 能够展现更加丰富的内容。 8 | - MIP-JS:可以保证 MIP-HTML 页面的快速渲染。 9 | - MIP-Cache:用于实现 MIP 页面的高速缓存,从而进一步提高页面性能。 10 | 11 | ## 1. MIP-HTML 12 | 13 | > info 14 | > 提示:MIP-HTML 基于 HTML 基础规范进行了扩展。 15 | 16 | 下面是一段简单的 MIP-HTML 代码示例: 17 | 18 | ```html 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 37 | 38 | 39 |event
18 |