新建專案工程
mkdir weex-starter
cd weex-starter
npm init -y
複製程式碼
然後在根目錄下新建index.html檔案。
目錄結構如下:
.
├── index.html
└── package.json
複製程式碼
安裝依賴
-
webpack & webpack-dev-server
由於weex-loader暫不支援webpack4,所以,webpack只能安裝3.x版本,webpack-dev-server對應安裝2.x版本npm i webpack@3.x webpack-dev-server@2.x -D 複製程式碼
-
babel相關
npm i babel-loader babel-core babel-preset-env -D // 新建.babelrc檔案 { "presets": ["env"] } 複製程式碼
-
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.jsnpm i weex-loader -D 複製程式碼
-
weex-vue-render
weex-vue-render是 Vue DSL 的 Web 渲染器, 它在 Web 上實現了 Weex 的內建元件和內建模組npm i weex-vue-render -S 複製程式碼
此時目錄結構如下(忽略node_modules):
. ├── index.html ├── package-lock.json └── package.json 複製程式碼
src目錄結構
mkdir -p src/entry src/page
複製程式碼
entry資料夾是webpack打包的入口,page資料夾是各個.vue頁面。
此時目錄結構如下(忽略node_modules):
.
├── index.html
├── package-lock.json
├── package.json
├── src
│ ├── entry
│ └── page
└── webpack.config.js
複製程式碼
編寫程式碼
weex最常見的使用場景就是編寫某一個頁面而不是整個APP,即開發一個一個的頁面,然後把這個頁面放到native端呈現。所以我們的weex-starter工程也是以頁面為單位組織的:src/entry資料夾下,一個入口檔案會編譯出一個頁面。
開發頁面是在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中。
<!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" }
"use weex:vue";
`,
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上怎麼看頁面效果。
native預覽
在開發程式碼時,我們已經動態生成了.weex.js,現在要做的就是把.weex.js以二維碼的形式展示出來。
現在是這麼簡單處理的:在當前頁面的左上角上顯示了一個二維碼,這個二維碼的內容正是當前頁面對應的.weex.js,然後用 Weex playground app 掃描這個二維碼就可以看到頁面在手機上渲染的真實效果。
如果覺得這個二維碼在開發的時候有點礙事,想開發一段時間之後再看native預覽效果,那你可以先把二維碼隱藏掉。
目前的這個效果只是達到了native預覽的目的,但是還有很大提升空間。我最終的想法是這樣的:頁面上有一個類似於蘋果手機的虛擬Home鍵,可以隨意拖動,當滑鼠hover它上面的時候,會以popover類似的效果展示出二維碼。
由於時間比較緊,這個效果並沒有開發出來,歡迎各位能夠提PR,共同完善這個weex-starter工程。github:github.com/jasonintju/…
Weex小冊系列:
Weex小冊—認識一下Weex
Weex小冊—從0搭建一個Weex專案
…未完待續
附招聘:
杭州阿里淘寶技術部基礎平臺招P6/P7前端。
你可能不知道基礎平臺部,但是你可能聽過Weex、Atlas、無人超市、EMAS等,這裡有頂尖的架構師團隊、移動AI團隊、演算法團隊、前端團隊、產品技術團隊,我們現在做的是EMAS跨平臺產品,歡迎優秀的前端工程師加入我們,簡歷傳送至 jasonintju@gmail.com,當然如果你有其他心儀的部門,我也可以幫忙內推。
招聘詳情
附我們美麗的產品小姐姐照片,歡迎來撩啊~