从0搭建一个Weex项目

新建项目工程

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
    复制代码

src目录结构

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上怎么看页面效果。

native预览

在开发代码时,咱们已经动态生成了.weex.js,如今要作的就是把.weex.js以二维码的形式展现出来。
如今是这么简单处理的:在当前页面的左上角上显示了一个二维码,这个二维码的内容正是当前页面对应的.weex.js,而后用 Weex playground app 扫描这个二维码就能够看到页面在手机上渲染的真实效果。

若是以为这个二维码在开发的时候有点碍事,想开发一段时间以后再看native预览效果,那你能够先把二维码隐藏掉。

目前的这个效果只是达到了native预览的目的,可是还有很大提高空间。我最终的想法是这样的:页面上有一个相似于苹果手机的虚拟Home键,能够随意拖动,当鼠标hover它上面的时候,会以popover相似的效果展现出二维码。

因为时间比较紧,这个效果并无开发出来,欢迎各位可以提PR,共同完善这个weex-starter工程。github:github.com/jasonintju/…

相关文章
相关标签/搜索