项目介绍

qtum-web-wallet 是量子链推出的网页版钱包。

项目地址 ​​https://github.com/qtumproject/qtum-web-wallet​

【Vue】从量子链网页钱包看vue项目结构以及开发部署最佳实践_前端

项目采用vue搭建。

通过网页可以实现钱包的创建备份转账以及智能合约的部署调用功能。

【Vue】从量子链网页钱包看vue项目结构以及开发部署最佳实践_vue_02

项目结构

【Vue】从量子链网页钱包看vue项目结构以及开发部署最佳实践_vue_03

这个vue项目采用了​​vue-loader​​,所以整体用的是嵌套结构。


  • build 构建脚本,还包括开发时候用的服务器配置
  • config 项目环境配置,区分开发环境和生产环境
  • dist 项目编译后导出的文件,部署生产环境的时候会用到
  • docs 项目内的说明文档,跟代码无关
  • src

    • assets 项目资源文件
    • components vue的组件文件,可以重复使用
    • controllers 对应项目的每个逻辑页面
    • libs 项目用到的封装的函数库


  • locales i18n国际化用到的语言字库文件

一些技术点

vue-i18n 国际化

官方文档的操作见后面的参考资料。

下面看这个项目是怎么做的。

引入库和配置文件

​package.json​​​ 中的​​devDependencies​​​引入​​"vue-i18n": "^7.4.2"​

​Vue.js​​​中引入​​import i18n from 'libs/i18n'​

import Vue from 'vue'
import VueI18n from 'vue-i18n'
import locales from 'locales'
import config from 'libs/config'

Vue.use(VueI18n)

export default new VueI18n({
locale: config.getLan(),
fallbackLocale: 'zh',
messages: locales.messages,
})

展示内容

在模板中,写法为​​{{ $t('create.title') }}​

获取配置

​src/lib/config.js​

getLan() {
let locale = this.get('lan')
navigator.languages.forEach(language => {
if (locale === undefined && locales.locales.indexOf(language) !== -1) {
locale = language
}
})
if (locale === undefined) {
locale = 'en'
}
return locale
},

更改配置

​src/controllers/Config.vue​

save: function() {
config.set('lan', this.lan)
config.set('network', this.network)
config.set('mode', this.mode)
window.location.reload()
}

build 构建项目

​package.json​​中

"scripts": {
"dev": "node build/dev-server.js",
"start": "node build/dev-server.js",
"build": "node build/build.js"
},

会执行​​node build/build.js​

require('./check-versions')()  //引入版本检测文件

process.env.NODE_ENV = 'production' //设定为生产模式

var ora = require('ora') //引入ora
var rm = require('rimraf') //node的rm -rf ,删除文件
var path = require('path')
var chalk = require('chalk') //Log格式工具可以指定颜色什么的
var webpack = require('webpack') //打包工具
var config = require('../config')
var webpackConfig = require('./webpack.prod.conf')

var spinner = ora('building for production...')
spinner.start()

rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
if (err) throw err
webpack(webpackConfig, function (err, stats) {
spinner.stop()
if (err) throw err
process.stdout.write(stats.toString({
colors: true,
modules: false,
children: false,
chunks: false,
chunkModules: false
}) + '\n\n')

if (stats.hasErrors()) {
console.log(chalk.red(' Build failed with errors.\n'))
process.exit(1)
}

console.log(chalk.cyan(' Build complete.\n'))
console.log(chalk.yellow(
' Tip: built files are meant to be served over an HTTP server.\n' +
' Opening index.html over file:// won\'t work.\n'
))
})
})

ora,就是build的时候那个会动的图标。 【Vue】从量子链网页钱包看vue项目结构以及开发部署最佳实践_html_04

重点还是在生产环境的文件中

var path = require('path')
var utils = require('./utils')
var webpack = require('webpack')
var config = require('../config')
var merge = require('webpack-merge')
var baseWebpackConfig = require('./webpack.base.conf')
var CopyWebpackPlugin = require('copy-webpack-plugin')
var HtmlWebpackPlugin = require('html-webpack-plugin')
var ExtractTextPlugin = require('extract-text-webpack-plugin')
var OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
var FaviconsWebpackPlugin = require('favicons-webpack-plugin')

var env = config.build.env

var webpackConfig = merge(baseWebpackConfig, {
module: {
rules: utils.styleLoaders({
sourceMap: config.build.productionSourceMap,
extract: true
})
},
devtool: config.build.productionSourceMap ? '#source-map' : false,
output: {
path: config.build.assetsRoot,
filename: utils.assetsPath('js/[name].[chunkhash].js'),
chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
},
plugins: [
// http://vuejs.github.io/vue-loader/en/workflow/production.html
new webpack.DefinePlugin({
'process.env': env
}),
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
},
sourceMap: true,
mangle: {
except: ['BigInteger', 'ECPair', 'Point']
}
}),
// extract css into its own file
new ExtractTextPlugin({
filename: utils.assetsPath('css/[name].[contenthash].css')
}),
// Compress extracted CSS. We are using this plugin so that possible
// duplicated CSS from different components can be deduped.
new OptimizeCSSPlugin({
cssProcessorOptions: {
safe: true
}
}),
// generate dist index.html with correct asset hash for caching.
// you can customize output by editing /index.html
// see https://github.com/ampedandwired/html-webpack-plugin
new HtmlWebpackPlugin({
filename: config.build.index,
template: 'index.html',
inject: true,
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
// more options:
// https://github.com/kangax/html-minifier#options-quick-reference
},
// necessary to consistently work with multiple chunks via CommonsChunkPlugin
chunksSortMode: 'dependency'
}),
new FaviconsWebpackPlugin({
logo: 'assets/images/logo.png',
inject: true,
title: 'Qtum Web Wallet',
icons: {
android: true,
appleIcon: true,
appleStartup: false,
favicons: true
}
}),
// keep module.id stable when vender modules does not change
new webpack.HashedModuleIdsPlugin(),
// split vendor js into its own file
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: function (module, count) {
// any required modules inside node_modules are extracted to vendor
return (
module.resource &&
/\.js$/.test(module.resource) &&
module.resource.indexOf(
path.join(__dirname, '../node_modules')
) === 0
)
}
}),
// extract webpack runtime and module manifest to its own file in order to
// prevent vendor hash from being updated whenever app bundle is updated
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest',
chunks: ['vendor']
}),
// copy custom static assets
new CopyWebpackPlugin([
{
from: path.resolve(__dirname, '../static'),
to: config.build.assetsSubDirectory,
ignore: ['.*']
}
])
]
})

if (config.build.productionGzip) {
var CompressionWebpackPlugin = require('compression-webpack-plugin')

webpackConfig.plugins.push(
new CompressionWebpackPlugin({
asset: '[path].gz[query]',
algorithm: 'gzip',
test: new RegExp(
'\\.(' +
config.build.productionGzipExtensions.join('|') +
')$'
),
threshold: 10240,
minRatio: 0.8
})
)
}

if (config.build.bundleAnalyzerReport) {
var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
webpackConfig.plugins.push(new BundleAnalyzerPlugin())
}

module.exports = webpackConfig

开发阶段和部署生产环境

开发阶段

本地安装

xiaoyu@LIXIAOYUdeMacBook-Pro.com➤ npm install

> fsevents@1.1.2 install /xiaoyu/qtumprojects/qtum-web-wallet/node_modules/fsevents
> node install

[fsevents] Success: "/xiaoyu/qtumprojects/qtum-web-wallet/node_modules/fsevents/lib/binding/Release/node-v57-darwin-x64/fse.node" already installed
Pass --update-binary to reinstall or --build-from-source to recompile

> phantomjs-prebuilt@2.1.15 install /xiaoyu/qtumprojects/qtum-web-wallet/node_modules/phantomjs-prebuilt
> node install.js

PhantomJS not found on PATH
Downloading https://github.com/Medium/phantomjs/releases/download/v2.1.1/phantomjs-2.1.1-macosx.zip
Saving to /var/folders/p6/3j5thk4j0972fw32188xdns80000gn/T/phantomjs/phantomjs-2.1.1-macosx.zip
Receiving...
[========================================] 100%
Received 16746K total.
Extracting zip contents
Removing /xiaoyu/qtumprojects/qtum-web-wallet/node_modules/phantomjs-prebuilt/lib/phantom
Copying extracted folder /var/folders/p6/3j5thk4j0972fw32188xdns80000gn/T/phantomjs/phantomjs-2.1.1-macosx.zip-extract-1520400588975/phantomjs-2.1.1-macosx -> /xiaoyu/qtumprojects/qtum-web-wallet/node_modules/phantomjs-prebuilt/lib/phantom
Writing location.js file
Done. Phantomjs binary available at /xiaoyu/qtumprojects/qtum-web-wallet/node_modules/phantomjs-prebuilt/lib/phantom/bin/phantomjs
added 1220 packages in 685.142s

运行,注意开发阶段跑的是dev

/xiaoyu/qtumprojects/qtum-web-wallet git:(master) [13:51:56]
xiaoyu@LIXIAOYUdeMacBook-Pro.com➤ npm run dev

> qtum-wallet@1.0.0 dev /xiaoyu/qtumprojects/qtum-web-wallet
> node build/dev-server.js

> Starting dev server...


WARNING Compiled with 1 warnings 1:54:48 PM

warning in ./src/controllers/RestoreMobile.vue

(Emitted value instead of an instance of Error) the "scope" attribute for scoped slots have been deprecated and replaced by "slot-scope" since 2.5. The new "slot-scope" attribute can also be used on plain elements in addition to <template> to denote scoped slots.

@ ./src/controllers/RestoreMobile.vue 7:0-357
@ ./~/babel-loader/lib!./~/vue-loader/lib/selector.js?type=script&index=0!./src/App.vue
@ ./src/App.vue
@ ./src/main.js
@ multi ./build/dev-client ./src/main.js

> Listening at http://localhost:8081

部署生产环境

开发环境的dev,运行的是项目自带的服务器,并且只要有文件更改,就会刷新,对于开发来讲很方便。

但是,上面运行着大量的辅助工具,导致整个项目运行的速度会变慢。

/xiaoyu/qtumprojects/qtum-web-wallet git:(master *) [14:10:39]
xiaoyu@LIXIAOYUdeMacBook-Pro.com➤ npm run build

> qtum-wallet@1.0.0 build /xiaoyu/qtumprojects/qtum-web-wallet
> node build/build.js

⠦ building for production...
Starting to optimize CSS...
Processing static/css/app.f1e81e8b885d40d5da38b1583c218b18.css...
Processed static/css/app.f1e81e8b885d40d5da38b1583c218b18.css, before: 301826, after: 301758, ratio: 99.98%
Hash: c444e4b2e6127e14174b
Version: webpack 2.7.0
Time: 38636ms
Asset Size Chunks Chunk Names
static/js/vendor.6b97dce258230f7e63ba.js 1.05 MB 0 [emitted] [big] vendor
static/js/app.6d3e646af7951a9ecaab.js 226 kB 1 [emitted] app
static/js/manifest.fb70284a5dffe96a9b58.js 1.51 kB 2 [emitted] manifest
static/css/app.f1e81e8b885d40d5da38b1583c218b18.css 302 kB 1 [emitted] [big] app
static/js/vendor.6b97dce258230f7e63ba.js.map 6.25 MB 0 [emitted] vendor
static/js/app.6d3e646af7951a9ecaab.js.map 848 kB 1 [emitted] app
static/css/app.f1e81e8b885d40d5da38b1583c218b18.css.map 351 kB 1 [emitted] app
static/js/manifest.fb70284a5dffe96a9b58.js.map 14.6 kB 2 [emitted] manifest
index.html 2.09 kB [emitted]

Build complete.

Tip: built files are meant to be served over an HTTP server.
Opening index.html over file:// won't work.

bulid之后的,将dist文件夹内的文件放到http服务器,比如apache nginx .就可以了。

【Vue】从量子链网页钱包看vue项目结构以及开发部署最佳实践_github_05

参考资料