mkdir weex-starter cd weex-starter npm init -y
而後在根目錄下新建index.html文件。
目錄結構以下:javascript
. ├── index.html └── package.json
webpack & webpack-dev-server
因爲weex-loader暫不支持webpack4,因此,webpack只能安裝3.x版本,webpack-dev-server對應安裝2.x版本css
npm i webpack@3.x webpack-dev-server@2.x -D
babel相關html
npm i babel-loader babel-core babel-preset-env -D // 新建.babelrc文件 { "presets": ["env"] }
vue相關vue
npm i vue -S // vue-loader配置項 npm i vue-loader autoprefixer postcss-plugin-weex postcss-plugin-px2rem weex-vue-precompiler -D
weex-loader
weex-loader的做用是把.vue文件轉化爲native端使用的.weex.jsjava
npm i weex-loader -D
weex-vue-render
weex-vue-render是 Vue DSL 的 Web 渲染器, 它在 Web 上實現了 Weex 的內置組件和內置模塊node
npm i weex-vue-render -S
此時目錄結構以下(忽略node_modules):webpack
. ├── index.html ├── package-lock.json └── package.json
mkdir -p src/entry src/page
entry文件夾是webpack打包的入口,page文件夾是各個.vue頁面。
此時目錄結構以下(忽略node_modules):git
. ├── index.html ├── package-lock.json ├── package.json ├── src │ ├── entry │ └── page └── webpack.config.js
weex最多見的使用場景就是編寫某一個頁面而不是整個APP,即開發一個一個的頁面,而後把這個頁面放到native端呈現。因此咱們的weex-starter工程也是以頁面爲單位組織的:src/entry文件夾下,一個入口文件會編譯出一個頁面。github
開發頁面是在web端進行的,因此咱們要依賴vue和weex-vue-render,可是.weex.js
是不須要這兩個庫的,由於 Weex 自己集成了v2版本的 Vue,而weex-vue-render是 Vue DSL 的 Web 渲染器
。開發以及打包編譯時,會同時生成.web.js和.weex.js,因此咱們把vue和weex-vue-render以<script>標籤的方式直接引入到html中。web
<!doctype html> <html> <head> ... <script src="./node_modules/vue/dist/vue.runtime.min.js"></script> <script src="./node_modules/weex-vue-render/dist/index.js"></script> </head> <body> <div id="root"></div> </body> </html>
// src/entry/index.js // import Vue from 'vue/dist/vue.esm'; // import weex from 'weex-vue-render'; import Index from '../page/index.vue'; // weex.init(Vue); Index.el = '#root'; new Vue(Index);
src/page/index.vue就是一個正常的.vue文件,內容本身編寫就行。
// webpack.common.js const path = require('path'); const fs = require('fs'); const webpack = require('webpack'); const entry = {}; ... // 遍歷src/entry文件夾下的一級js文件作打包入口,即entry/*.js const webConfig = { entry, output: { filename: '[name].web.js', path: path.resolve(__dirname, 'dist'), publicPath: 'dist/' }, module: { rules: [ { test: /\.js$/, use: ['babel-loader'] }, { test: /\.vue(\?[^?]+)?$/, use: [ { loader: 'vue-loader', options: { ... // 這個地方的配置參考 https://github.com/weexteam/weex-vue-render } } ] } ] }, plugins: [] }; const weexConfig = { entry, output: { filename: '[name].js', path: path.resolve(__dirname, 'dist') }, module: { rules: [ { test: /\.js$/, use: ['babel-loader'] }, { test: /\.vue(\?[^?]+)?$/, use: ['weex-loader'] } ] }, plugins: [ // 打包後的.weex.js的頭部加上如下banner才能被native識別 new webpack.BannerPlugin({ banner: '// { "framework": "Vue" }\n"use weex:vue";\n', raw: true }) ] }; module.exports = [webConfig, weexConfig];
打包編譯js分開發環境和生成環境,生成環境,直接打包webpack.common.js的配置就行,每個頁面會打包出對應的.web.js和.weex.js。
// webpack.prod.conf.js const path = require('path'); const rimraf = require('rimraf'); const UglifyJSPlugin = require('uglifyjs-webpack-plugin'); const commonConfig = require('./webpack.common'); const [webConfig, weexConfig] = commonConfig; webConfig.plugins.push(new UglifyJSPlugin()); weexConfig.plugins.unshift(new UglifyJSPlugin()); // 是unshift,要先壓縮js,後加banner rimraf.sync(path.resolve(__dirname, 'dist')); // 刪除dist文件夾 module.exports = [webConfig, weexConfig];
開發環境時,咱們會起一個devServer,server在內存中會生成對應的.web.js,可是此時還須要生成.weex.js,由於開發的時候咱們不只要在web上看效果,還要在native端看效果。
// webpack.dev.conf.js ... const weexConfig = webpackMerge(commonConfig[1], { watch: true }); // 以Node.js API的方式執行webpack生成weex.js,https://webpack.js.org/api/node/ webpack(weexConfig, (err, stats) => { if (err) { console.err('COMPILE ERROR:', err.stack); } }); const webConfig = webpackMerge(commonConfig[0], { devServer: { ... } }); // 尋找可用的端口號 portfinder.getPort((err, port) => { if (err) { console.log(err); } else { webConfig.devServer.port = port; } }); module.exports = webConfig;
若是一個工程只能用來開發一張頁面未免太奢侈了,因此webpack打包entry配置的是多入口,這樣就能夠在一個工程裏面開發多個頁面,想查看不一樣的頁面時,修改一下瀏覽器的url便可,基於此,作出瞭如下改動:
// index.html ... <script> // 這段js的意思是:默認加載dist文件夾下的index.web.js,若是想查看另外一個頁面,把url中的page=index.web.js改爲其餘的js便可 // 好比page=home.web.js,此時查看的就是home.vue的內容 ;(function () { var defaultPage = 'index.web.js' var match = location.search.match(new RegExp('[?|&]page=([^&]+)')) var page = match && match[1] if (!page) { return location.href = location.href.replace(/\?|$/, function (f) { var query = '?page=' + defaultPage return f ? query + '&' : query }) } var $script = document.createElement('script') $script.src = './dist/' + page document.body.appendChild($script) })(); </script>
此時目錄結構以下(忽略node_modules):
. ├── .babelrc ├── index.html ├── package-lock.json ├── package.json ├── src │ ├── entry │ │ ├── home.js │ │ └── index.js │ └── page │ ├── home.vue │ └── index.vue ├── webpack.common.js ├── webpack.dev.conf.js └── webpack.prod.conf.js
其實,開發weex頁面的工程已經完成了,咱們實現了一個.vue文件能夠打包編譯成.web.js和.weex.js。可是,少了一個環節有沒有覺察到?——打包出來的.weex.js在native上怎麼看頁面效果。
在開發代碼時,咱們已經動態生成了.weex.js,如今要作的就是把.weex.js以二維碼的形式展現出來。
如今是這麼簡單處理的:在當前頁面的左上角上顯示了一個二維碼,這個二維碼的內容正是當前頁面對應的.weex.js,而後用 Weex playground app 掃描這個二維碼就能夠看到頁面在手機上渲染的真實效果。
若是以爲這個二維碼在開發的時候有點礙事,想開發一段時間以後再看native預覽效果,那你能夠先把二維碼隱藏掉。
目前的這個效果只是達到了native預覽的目的,可是還有很大提高空間。我最終的想法是這樣的:頁面上有一個相似於蘋果手機的虛擬Home鍵,能夠隨意拖動,當鼠標hover它上面的時候,會以popover相似的效果展現出二維碼。
因爲時間比較緊,這個效果並無開發出來,歡迎提PR,共同完善這個weex-starter工程。github:https://github.com/jasonintju/weex-starter