一個NW.js+Webpack+Gulp+React的Hello World

前言

還記得第一次接觸NW.js時,這玩意還叫做node-webkit,當時非常欣喜看完了官網的所有demo,感覺還不錯,後來就把它晾在一邊了。結果現在已經更名爲NW(現在還有類似的平臺electron),真是Time flies~ 現在就結合所學所瞭解到的Webpack、Gulp、React、Materialize、Babel這些工具在NW.js平臺上寫一個新工程Hello world,以後會在這個工程基礎上用不同的分支做點小程序,就當是編程練手-_-||

NW.js簡介與安裝

NW.js是基於Node.js和Chromium的一個平臺,結合了前端開發的便捷與Node強大API兩方面的優點,可以用HTML和JavaScript寫桌面級應用程序,並可以在DOM中直接調用Node.js模塊。也就是說,NW.js使用純JavaScript相關技術編寫桌面應用,並可以打包成Mac、Windows、Linux不同平臺的本地應用。官網的一句話介紹:

NW.js (previously known as node-webkit) lets you call all Node.js modules directly from DOM and enables a new way of writing applications with all Web technologies.

安裝NW.js十分簡單,直接在官網下載NORMAL或者SDK版本,區別是前者不能調出Chromium調試工具(但是體積較小)。我下載的是SDK v0.25.0。在Windows平臺下載解壓後,直接雙擊nw.exe即可運行出NW.js的平臺界面:
這裏寫圖片描述

可以看出這個版本是基於Node v8.4.0+Chromium 61.0。由於Mac和Windows上的命令行中啓動NW.js的命令一個是nwjs,一個是nw,我就直接把Windows下的nw.exe更名爲nwjs.exe,然後將該目錄添加到環境變量,這樣就可以直接在命令行中啓動NW.js,而且啓動方法與Mac下的基本一致。(我寢室用的Mac機房用的Windows,爲了能在兩個系統下都能直接運行代碼,就要解決命令行中nwjs與nw的差異)

在NW.js上寫一個簡單的Hello world可以參見這篇文章: 繼續挖坑之 NW.js (一) 介紹

項目結構一覽

先看看項目的基本文件結構,如下所示:

.babelrc
│  gulpfile.js
│  package.json
│  webpack.config.js
│
├─dist
├─node_modules
├─out
└─src
    ├─app
    │      main.js
    ├─assets
    │      icon.png
    ├─style
    │      style.css
    └─view
            index.html

說明:

  • dist:存放Webpack打包後的文件
  • node_modules:第三方包,使用NPM管理
  • out:放的是使用NW打包成本地應用,在Mac環境中裏面就會生成一個.app文件
  • src:項目源碼,.js、圖片資源、.css、.html分別放在app、assets、style、view文件夾中
  • .babelrc:Babel配置文件
  • gulpfile.js:Gulp配置文件及入口
  • package.json:NW.js與NPM共同配置文件(主要是兩者都叫package.json,我就索性合在一起)
  • webpack.config.js:Webpack配置文件及入口

自己感覺項目的結構還是比較清晰的^_^,下面就從零開始講下項目的配置。

Getting Started

首先建一個nw-app文件夾,然後使用NPM初始化:

F:\>mkdir nw-app
F:\>cd nw-app
F:\nw-app>npm init

然後把項目中相關文件夾建好,之後就要修改項目中的package.json文件,使之能滿足NW.js的格式要求。這裏給出NW.js配置文件的官網文檔鏈接:Manifest Format 一個基本的NW.js配置文件及說明如下:

{
  "main": "index.html",  //入口文件
  "version": "1.0.0",  //版本,打包的時候需要
  "name": "nw-demo",  //程序名
  //窗口設置
  "window": {
    "resizable": true,
    "min_width": 900,
    "min_height": 600,
    "icon": "assets/icon.png"  //程序圖標
  }
}

將這些信息添加到NPM的配置文件package.json中,如下:

{
  "name": "NW-Demo",
  "version": "1.0.0",
  "description": "一個nw.js+gulp+webpack+react+materialize開發demo",
  "main": "./index.html",//package.json和index.html會被打包到dist文件夾下,所以就是同一目錄
  "window": {
    "resizable": true,
    "min_width": 900,
    "min_height": 600,
    "icon": "assets/icon.png"
  },
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
  }
}

React+Materialize

由於項目中使用的框架和UI是React和Materialize,先要用NPM安裝下:

npm install --save-dev react
npm install --save-dev react-dom
npm install --save-dev materialize-css
npm install --save-dev jquery

然後在index.html中寫一個基本的HTML代碼作爲程序入口:

<!DOCTYPE html>
<html>
<head>
    <title>NW-Demo</title>
    <meta charset="utf-8">
    <style type="text/css">
        html, body, #root{
            width: 100%;
            height: 100%;
            padding: 0;
            margin: 0;
            overflow: hidden;
            background-color: #ccc;
        }   
    </style>
</head>
<body>
<div id="root"></div>
</body>
</html>

在main.js中是一個React組件,需要注意的是使用materialize-css前要引入jquery、materialize.css、materialize.js:

require("jquery");  //jquery要先引入
require("materialize-css/dist/css/materialize.css");
require("materialize-css/dist/js/materialize.js");

let React = require('react');
let ReactDOM = require('react-dom');

class HelloWorld extends React.Component {
  render() {
    return (
        <div className="row">
            <div className="col s6 offset-s3">
              <div className="card blue-grey darken-1">
                <div className="card-content white-text">
                  <span className="card-title">Hello</span>
                  <p>NW.js + Gulp + Webpack + React + Materialize</p>
                </div>
              </div>
            </div>
        </div>
    );
  }
}

ReactDOM.render(<HelloWorld/>, document.getElementById('root'));

這樣一個基本的Hello world就差不多了,接下來就是使用Webpack+Babel打包項目。

Webpack+Babel

由於項目中存在圖片、字體(materialize會自動引用)、.json(需要將package.json複製到dist文件夾)、HTML、CSS文件、JSX轉換,所以使用Webpack要解決這些文件。
首先安裝Webpack和Babel:

#Webpack
npm install --save-dev webpack style-loader html-webpack-plugin file-loader css-loader copy-webpack-plugin

#Babel
npm install --save-dev babel-core babel-preset-es2015 babel-preset-react

由於我想直接在使用Webpack打包的時候使用Babel,還需要安裝babel-loader:

npm install --save-dev babel-loader

然後在項目中添加webpack.config.js文件:

const path = require('path');
//用於icon和package.json
const CopyWebpackPlugin = require('copy-webpack-plugin');
//HTML
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack');

module.exports =
{  module: {
    rules: [
      //JSX & JS, Babel轉碼
      {
        test: /\.jsx?$/,
        use: ['babel-loader']
      },
      // CSS
      {
        test: /\.css$/, 
        use: ["style-loader", "css-loader"]
      },
      // font
      {
        test: /\.(eot|woff(2)?)(\?[a-z0-9=&.]+)?$/,
        use: [
          {
            loader: 'file-loader',
            options: {outputPath: "font/"}  
          }
        ]
      }
    ]
  },
    entry: {
        main: "./src/app/main.js"
    },
    output:{
        path : path.resolve(__dirname, "./dist"),//需要絕對路徑
        filename : "[name].js",
    },
    plugins: [
        new HtmlWebpackPlugin({
          title: 'NW-Demo',
          filename: 'index.html',
        inject: 'body',
          template: "src/view/index.html",
        chunks: ['main']
      }),
    new CopyWebpackPlugin([
      //導入icon
      {
        from: path.resolve(__dirname, './src/assets/icon.png'),
        to: 'assets/icon.png'
      },
      //導入package.json
      {
        from: path.resolve(__dirname, './package.json'),
        to: 'package.json'
      }
      ])
    ]
};

添加Babel配置文件.babelrc:

//.babelrc
{
  "presets": [
    "react",
    "es2015"
  ],
    "ignore":[
        "jquery.js",
        "jquery.min.js",
        "materialize.js",
        "materialize.min.js"
    ]
}

最後在package.json的scripts中添加幾條命令:

  "scripts": {
    "start": "nwjs dist", //在dist目錄啓動NW.js
    "build": "webpack --display-reasons", //使用Webpack打包
    "mw-prod": "nwbuild -p win64 -o out/ dist/"  //NW打包,需要安裝nwbuild包
  }

大功告成!
在命令行中輸入npm run build, 打包結束後輸入npm run start ,就可以看到Hello world界面了:
這裏寫圖片描述

使用Gulp進行自動化構建

最後,我在這個項目中使用了Gulp進行自動構建。主要就是針對Webpack打包和NW.js打包,其配置文件gulpfile.js內容如下:

let gulp = require('gulp');
let clean = require('gulp-clean');
let shell = require('gulp-shell');
let webpack = require('webpack');
let webpack_config = require('./webpack.config.js');

//Webpack編譯
gulp.task('run', ['webpack'] ,shell.task(['npm run start']));
gulp.task('webpack', ['clean'], function(cb) {
     webpack(webpack_config, function(err, stats) {
        if(err) throw new Error(err);
        console.log(stats.compilation.fileDependencies);
        cb();
    });
});
gulp.task('clean', function(cb){
    return gulp.src('dist', {read: false}).pipe(clean());
    cb();
});

//NW打包
gulp.task('prod', ['clean-out'] ,shell.task(['npm run mw-prod']));
gulp.task('clean-out', function(cb){
    return gulp.src('out', {read: false}).pipe(clean());
    cb();
});

由其中的引用可知,需要先在項目中安裝gulp、gulp-clean、gulp-shell。

然後修改package.json中的scripts:

  "scripts": {
    "start": "nwjs dist",
    "build": "gulp run",
    "prod": "gulp prod"
  }

這樣每次編譯或者打包的時候就會先清理原來的文件,然後自動啓動NW.js。

大功告成 again !

代碼地址:
https://git.oschina.net/liuyaqi/nw-app.git

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章