Weex小冊—從0搭建一個Weex專案

無名小貝勒發表於2019-03-04

新建專案工程

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.js

    npm 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" }\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上怎麼看頁面效果。

native預覽

在開發程式碼時,我們已經動態生成了.weex.js,現在要做的就是把.weex.js以二維碼的形式展示出來。
現在是這麼簡單處理的:在當前頁面的左上角上顯示了一個二維碼,這個二維碼的內容正是當前頁面對應的.weex.js,然後用 Weex playground app 掃描這個二維碼就可以看到頁面在手機上渲染的真實效果。

Weex小冊—從0搭建一個Weex專案

如果覺得這個二維碼在開發的時候有點礙事,想開發一段時間之後再看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,當然如果你有其他心儀的部門,我也可以幫忙內推。 招聘詳情

附我們美麗的產品小姐姐照片,歡迎來撩啊~

Weex小冊—從0搭建一個Weex專案
Weex小冊—從0搭建一個Weex專案

相關文章