hi,你好!欢迎访问本站!登录
本站由网站地图腾讯云宝塔系统阿里云强势驱动
当前位置:首页 - 教程 - 杂谈 - 正文 君子好学,自强不息!

【原创】从零开始搭建Electron+Vue+Webpack项目框架,一套代码,同时构建客户端、web端(二)

2019-11-18杂谈搜奇网26°c
A+ A-

导航:

(一)Electron跑起来
(二)从零搭建Vue百口桶+webpack项目框架
(三)Electron+Vue+Webpack,团结调试全部项目(未完待续)
(四)Electron设置润饰(未完待续)
(五)预加载及自动更新(未完待续)
(六)构建、宣布全部项目(包含client和web)(未完待续)

择要上篇文章说到了怎样新建工程,并启动一个最简朴的Electron运用。“跑起来”了Electron,那就接着把Vue“跑起来”吧。有一点须要申明的是,webpack是贯串这个系列一直的,我也是本着进修的立场,去引见、总结一些常用到的设置及思绪,有不恰当的处所,或许待优化的处所,迎接留言。项目完全代码:https://github.com/luohao8023/electron-vue-template

下面最先~~~

一、装置依靠 vue、webpack:不多说了 vue-loader:剖析、转换.vue文件 vue-template-compiler:vue-loader的依靠包,但又独立于vue-loader,简朴的说,作用就是运用这个插件将template语法转为render函数 webpack-dev-server:疾速搭建当地运转环境的东西 webpack-hot-middleware:搭配webpack-dev-server运用,完成热更新 chalk:敕令行输出带有色彩的内容 依靠包就引见这么多,背面须要什么能够自行下载,这里不多赘述了。   二、完美工程目次    webpack.render.config.js:衬着历程打包设置 dev.js:当地调试剧本 views:页面代码 index.js:vue工程进口文件 index.ejs:打包生成html文件时的模板 三、设置Vue工程 1、编写进口文件,render>index.js
import Vue from 'vue';
import index from './views/index.vue';

//作废 Vue 一切的日记与正告
Vue.config.silent = true;
new Vue({
    el: '#app',
    render: h => h(index)
});

2、编写根组件,render>views>index.vue

<template>
    <div class="content">
        <h1>Welcome to electron-vue-template!</h1>
    </div>
</template>

<script>
export default {}
</script>
<style></style>

3、编写html模板文件,render>index.ejs,webpack剖析、打包vue文件时,以此模板生成html文件

<!DOCTYPE html>
<html lang="zh-CN">
<!--template for 2019年10月30日-->
<!--<%= new Date().getFullYear()+'/'+(new Date().getMonth()+1)+'/'+new Date().getDate()+' '+new Date().getHours()+':'+new Date().getMinutes() %>-->
<head>
    <meta charset="UTF-8">
    <title>模板文件</title>
    <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=0">
    <meta HTTP-EQUIV="pragma" CONTENT="no-cache">
    <meta HTTP-EQUIV="Cache-Control" CONTENT="no-store, must-revalidate">
    <meta HTTP-EQUIV="expires" CONTENT="Wed, 26 Feb 1997 08:21:57 GMT">
    <meta HTTP-EQUIV="expires" CONTENT="0">
</head>
<body>
    <div id="app"></div>
</body>
</html>

4、编写webpack设置文件,builder>webpack.render.config.js,发起依据本文这类体式格局,把设置文件零丁抽出来,如许的话,当地调试和打包能够共用一套设置,只须要通报差别参数就能够了,不要把一切的设置和打包逻辑写在一个文件里,太长、太乱、太难保护

/*
Name:    衬着历程设置
Author: haoluo
Date:   2019-10-30
 */
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const devMode = process.env.NODE_ENV === 'development';

module.exports = {
    mode: devMode ? 'development' : 'production',
    entry: {
        main: './src/render/index.js'
    },
    output: {
        path: path.join(__dirname, '../app/'),
        publicPath: devMode ? '/' : '',
        filename: './js/[name].[hash:8].js'
    },
    module: {
        rules: [
            {
                test: /\.vue$/,
                exclude: /node_modules/,
                loader: 'vue-loader'
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: './src/render/index.ejs',
            filename: './index.html',
            title: 'electron-vue-template',
            inject: false,
            hash: true,
            mode: devMode
        })
    ]
}

恰当解释一下:

mode:环境参数,针对差别的环境,webpack内部有一些差别的机制,并对响应环境做响应的优化

entry:进口,webpack实行构建的第一步将从进口文件最先,递归查询并剖析一切依靠的模块。设置体式格局有多种,可参考webpack文档,这里我们设置的途径是'./src/render/index.js',意义是src目次下,render文件夹下的index.js,而webpack设置文件是在builder文件夹下,那这个“./”的相对途径究竟是相对于谁呢?这就得说一下webpack中的途径题目了,context 是 webpack 编译时的基本目次,进口出发点(entry)会相对于此目次查找,那这个context又是个什么东西?webpack源码有关默许设置中有这么一句话

this.set("context", process.cwd());

这就是context的默许值,工程的根目次,那这个entry的设置就很好理解了。

output:打包的输入设置,途径发起设置为绝对途径。

module和plugins就不多说了。

5、编写当地调试剧本

/**
* Tip:    调试衬着历程
* Author: haoluo
* Data:   2019-10-30
**/
process.env.NODE_ENV = 'development';
const webpack = require('webpack');
const WebpackDevServer = require('webpack-dev-server');
const webpackHotMiddleware = require('webpack-hot-middleware');
const chalk = require('chalk');
const http = require('http');
function devRender() {
    console.log('启动衬着历程调试......');
    const webpackDevConfig = require('./webpack.render.config.js');
    const compiler = webpack(webpackDevConfig);
    new WebpackDevServer(
        compiler, {
            contentBase: webpackDevConfig.output.path,
            publicPath: webpackDevConfig.output.publicPath,
            open: true,//翻开默许浏览器
            inline: true,//革新形式
            hot: true,//热更新
            quiet: true,//除第一次编译外,其他不显现编译信息
            progress: true,//显现打包进度
            setup(app) {
                app.use(webpackHotMiddleware(compiler));
                app.use('*', (req, res, next) => {
                    if (String(req.originalUrl).indexOf('.html') > 0) {
                        getHtml(res);
                    } else {
                        next();
                    }
                });
            }
        }
    ).listen(8099, function(err) {
        if (err) return console.log(err);
        console.log(`Listening at http://localhost:8099`);
    });
    compiler.hooks.done.tap('doneCallback', (stats) => {
        const compilation = stats.compilation;
        Object.keys(compilation.assets).forEach(key => console.log(chalk.blue(key)));
        compilation.warnings.forEach(key => console.log(chalk.yellow(key)));
        compilation.errors.forEach(key => console.log(chalk.red(`${key}:${stats.compilation.errors[key]}`)));
        console.log(chalk.green(`${chalk.white('衬着历程调试终了\n')}time:${(stats.endTime-stats.startTime)/1000} s`));
    });
}

function getHtml(res) {
    http.get(`http://localhost:8099`, (response) => {
        response.pipe(res);
    }).on('error', (err) => {
        console.log(err);
    });
}

devRender();

都是一些通例操纵,能够浏览一下代码。

6、设置启动敕令,在package.json中新增dev敕令,启动当地调试(先起了再说,报错什么的,见招拆招)

  "scripts": {
    "start": "electron ./src/main/main.js",
    "dev": "node ./builder/dev.js"
  },

然后敕令行运转npm run dev。。。。。。横竖我这儿是报错了。。。说是找不到html-webpack-plugin模块,那就运转npm i html-webpack-plugin -D装置一下,假如步骤一没有做的话,背面能够还会碰到许多模块找不到的状况,解决要领很简朴,缺什么装置什么就好了。装置完一切的模块以后,启动,照样报错了。。。。。。

ModuleNotFoundError: Module not found: Error: Can't resolve 'vue' in ...
ModuleNotFoundError: Module not found: Error: Can't resolve 'vue-loader' in ...

搜检了下package.json文件和node_modules,发明我的vue-loader没有装,然后就是装一下(假如没有碰到这个步骤,能够疏忽)

再次运转

  

这个报错就很友爱了吗,就是vue-loader通知你,必需装置vue-template-compiler插件,不然就不事情,那就装一下。

接着运转,就晓得没那末轻易胜利

  

vue-loader报错说缺少了插件,让搜检是不是设置了VueLoaderPlugin插件,搜一下这是个什么鬼,看这里,15+版本的vue-loader须要合营VueLoaderPlugin运用,然后看了一下我运用的vue-loader版本15.7.1,那就配一下这个东西。

  

接着运转,终究没有报错了,然则页面为啥子是白的,我的h1标签呢?冷静下来剖析一下题目,页面没有东西申明我打包时生成的html文件有题目(devServer会把打包出来的静态文件保留在内存里),而html文件是依据ejs模板生成的,那会不会是模板设置有题目?

  

看一下我们的模板,构造是没什么题目啊,然则,没有援用css和js文件啊,也就是我们辛辛苦苦剖析vue文件,打包css和js,末了却没有援用。。。好吧,那就再设置一下ejs模板,把响应的文件引入一下

<!DOCTYPE html>
<html lang="zh-CN">
<!--template for 2019年10月30日-->
<!--<%= new Date().getFullYear()+'/'+(new Date().getMonth()+1)+'/'+new Date().getDate()+' '+new Date().getHours()+':'+new Date().getMinutes() %>-->
<%
function getFilePath(filename,libsPath){
    let _filenameSearchIndex=filename.indexOf("?");
    let _libsPathSearchIndex=libsPath.indexOf("?");
    let _filename=filename.substr(0,_filenameSearchIndex<1?filename.length:_filenameSearchIndex);
    let _libsPath=libsPath.substr(0,_libsPathSearchIndex<1?libsPath.length:_libsPathSearchIndex);
    let htmlfilename=path.relative(_filename,_libsPath);
    return libsPath;
}
let path = require('path'),jsArr = [],cssArr = [];
let filename="./index.html";
    //修正目次构造
    for(let i=0;i<htmlWebpackPlugin.files.css.length;i++){
        let name=getFilePath(filename,String(htmlWebpackPlugin.files.css[i]));
        cssArr.push(name);
    }
    for(let i=0;i<htmlWebpackPlugin.files.js.length;i++){
        let name=getFilePath(filename,String(htmlWebpackPlugin.files.js[i]));
        jsArr.push(name);
    }
%>
<head>
    <meta charset="UTF-8">
    <title><%= htmlWebpackPlugin.options.title %></title>
    <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=0">
    <meta HTTP-EQUIV="pragma" CONTENT="no-cache">
    <meta HTTP-EQUIV="Cache-Control" CONTENT="no-store, must-revalidate">
    <meta HTTP-EQUIV="expires" CONTENT="Wed, 26 Feb 1997 08:21:57 GMT">
    <meta HTTP-EQUIV="expires" CONTENT="0">
    <% cssArr.forEach(css=>{ %><link rel="stylesheet" href="<%= css %>" />
    <% }) %>
</head>
<body>
    <div id="app"></div>
    <% jsArr.forEach(js=>{ %><script type="text/javascript" src="<%= js %>"></script>
    <% }) %>
</body>
</html>

我们能够在ejs中拿到html-webpack-plugin插件的一些信息,比方插件设置、生成的文件等,然后拿到js和css文件,并引入进来,这里发起看一下ejs模板语法。

我们接着运转,终究出来了。

  

7、设置打包剧本

在builder文件夹下新建build.js,引入设置,直接运转webpack打包即可,不须要devServer。

/**
* Tip:    打包
* Author: haoluo
* Data:   2019-10-30
**/
process.env.NODE_ENV = 'production';
const chalk = require("chalk");
const del = require("del");
const webpack = require('webpack');
const renderConfig = require('./webpack.render.config.js');

del(["./app/*"]); //删除汗青打包数据

viewBuilder().then(data => {
    console.log("打包输出===>", data)
}).catch(err => {
    console.error("打包失足,输出===>", err);
    process.exit(1);
});

function viewBuilder() {
    return new Promise((resolve, reject) => {
        console.log("打包衬着历程......");
        const renderCompiler = webpack(renderConfig);
        renderCompiler.run((err, stats) => {
            if (err) {
                console.log("打包衬着历程碰到Error!");
                reject(chalk.red(err));
            } else {
                let log = "";
                stats.compilation.errors.forEach(key => {
                    log += chalk.red(`${key}:${stats.compilation.errors[key]}`) + "\n";
                })
                stats.compilation.warnings.forEach(key => {
                    log += chalk.yellow(key) + "\n";
                })
                Object.keys(stats.compilation.assets).forEach(key => {
                    log += chalk.blue(key) + "\n";
                })
                log += chalk.green(`time:${(stats.endTime-stats.startTime)/1000} s\n`) + "\n";
                resolve(`${log}`);
            }
        })
    })
}

在package.json中新增打包敕令

"scripts": {
    "start": "electron ./src/main/main.js",
    "dev": "node ./builder/dev.js",
    "build": "node ./builder/build.js"
  },

npm run build实行打包,此次还真是出奇的顺遂啊,看一下app文件夹,已生成了静态文件,然后直接在浏览器翻开index.html文件,一般显现。

 

四、运用vuex,vue-router,axios

说好的百口桶呢,这里我们不必vue-resource了,运用axios。

1、运用vuex

装置vuex依靠,在src>render文件夹下新建store文件夹,并在store文件夹下新增:

actions.js

export default {}

index.js

import Vue from 'vue';
import Vuex from 'vuex';
import actions from './actions.js';
import mutations from './mutations.js';
Vue.use(Vuex);
// 这里为全局的,模块内的请在模块内动态注册
const store = new Vuex.Store({
    strict: true,
    state: {
        userInfo: {
            name: 'haoluo',
            address: 'beijing'
        }
    },
    getters: {},
    mutations,
    actions
});
export default store;

mutations.js

export default {
    //设置用户信息
    setUserInfo(state, config) {
        if (!config) {
            state.userInfo = {};
        }
        for (var objName in config) {
            state.userInfo[objName] = config[objName];
        }
    }
}

以上三个文件的气力代码,比官网教程还简朴,能够自行研究一下文档。

文件建好以后,须要把store挂载到vue实例上,找到vue工程的进口文件,src>render>index.js

import Vue from 'vue';
import store from './store/index.js';
import index from './views/index.vue';

//作废 Vue 一切的日记与正告
Vue.config.silent = true;
new Vue({
    el: '#app',
    store: store,
    render: h => h(index)
});

然后我们就能够运用啦,找到根组件,src>render>views>index.vue

<template>
    <div class="content">
        <h1>Welcome to electron-vue-template!</h1>
        <h2>name:{{userInfo.name}}</h2>
        <h2>address:{{userInfo.address}}</h2>
    </div>
</template>

<script>
import {mapState} from 'vuex';
export default {
    computed: {
        ...mapState(['userInfo'])
    }
}
</script>
<style></style>

mapState是state的辅佐函数,是个语法糖,借助mapState我们能够更方面的猎取属性,而不须要写一堆啰里吧嗦的东西,经由过程盘算属性computed吸收userInfo,然后就能够运用啦,运转当地调试,发明页面上已能够一般显现了

属性有了以后我们能够运用,但假如想要转变vuex中存储的属性呢?为了保证单向数据流以及轻易对数据的追踪等一些其他缘由,不发起直接修正vuex的属性,而是须要经由过程mutations,这里也有一个辅佐函数mapMutations,用法同mapState相似,只不过须要用methods去吸收,作为一个全局要领运用

<!-- render>views>index.vue -->
<template>
    <div class="content">
        <h1>Welcome to electron-vue-template!</h1>
        <h2>name:{{userInfo.name}}</h2>
        <h2>address:{{userInfo.address}}</h2>
        <button @click="changeAddress">设置address为tianjin</button>
    </div>
</template>

<script>
import {mapState,mapMutations} from 'vuex';
export default {
    computed: {
        ...mapState(['userInfo'])
    },
    methods: {
        ...mapMutations(['setUserInfo']),
        changeAddress() {
            this.setUserInfo({
                address: 'tianjin'
            });
        }
    }
}
</script>
<style></style>

当点击按钮的时刻。userInfo中的address被修正了,页面衬着的值也响应的转变了

 

2、运用vue-router

装置vue-router依靠,在render文件夹下新增router文件夹,并在个中新增index.js

module.exports = [
    {
        path: '/index.html',
        name: 'index',
        meta: {
            title: '首页',
            author: '--',
            parentRouter: '--'
        },
        component: (resolve) => {
            require.ensure([], () => {
                return resolve(require('../views/index.vue'))
            }, "index")
        },
        children: []
    }
];

在进口文件render>index.js中引入并挂载

// render>index.js
import Vue from 'vue';
import VueRouter from 'vue-router';
import store from './store/index.js';
import routers from './router/index.js';
import index from './views/index.vue';

Vue.use(VueRouter);

let router = new VueRouter({
    routes: routers
})

//作废 Vue 一切的日记与正告
Vue.config.silent = true;
new Vue({
    el: '#app',
    router: router,
    store: store,
    render: h => h(index)
});

运转一下,页面能够一般显现,在地址栏输入http://localhost:8099/index.html时,也是没有题目的,如今新增添一个页面,定单页

<template>
    <div class="content">
        <h1>order page!</h1>
    </div>
</template>

<script>
export default {}
</script>
<style></style>

再设置下路由

module.exports = [
    {
        path: '/index.html',
        name: 'index',
        meta: {
            title: '首页',
            author: '--',
            parentRouter: '--'
        },
        component: (resolve) => {
            require.ensure([], () => {
                return resolve(require('../views/index.vue'))
            }, "index")
        },
        children: []
    },
    {
        path: '/order.html',
        name: 'order',
        meta: {
            title: '定单页',
            author: '--',
            parentRouter: '--'
        },
        component: (resolve) => {
            require.ensure([], () => {
                return resolve(require('../views/order.vue'))
            }, "order")
        },
        children: []
    }
];

并在首页index.vue中增添跳转按钮,运转以后,发明跳不过去,为难~~~,路由跳转,须要有<router-view></router-view>去吸收才行啊

革新一下吧,views下新增home.vue,把index.vue中的内容拷贝过去,index.vue改成下面如许

<!-- render>views>index.vue -->
<template>
    <div>
        <router-view></router-view>
    </div>
</template>

<script>
export default {
    methods: {},
    mounted() {
        this.$router.push({
            name: 'home'
        });
    }
}
</script>
<style></style>

router文件改成下面如许

module.exports = [
    {
        path: '/index.html',
        name: 'index',
        meta: {
            title: '首页',
            author: '--',
            parentRouter: '--'
        },
        component: (resolve) => {
            require.ensure([], () => {
                return resolve(require('../views/index.vue'))
            }, "index")
        },
        children: [
            {
                path: '/home.html',
                name: 'home',
                meta: {
                    title: 'home页',
                    author: '--',
                    parentRouter: '--'
                },
                component: (resolve) => {
                    require.ensure([], () => {
                        return resolve(require('../views/home.vue'))
                    }, "home")
                },
                children: []
            },
            {
                path: '/order.html',
                name: 'order',
                meta: {
                    title: '定单页',
                    author: '--',
                    parentRouter: '--'
                },
                component: (resolve) => {
                    require.ensure([], () => {
                        return resolve(require('../views/order.vue'))
                    }, "order")
                },
                children: []
            }
        ]
    }
];

再次运转,页面已能够一般跳转了。

3、axios,这里临时不说,后续electron和vue联调的时刻会补上。

几点申明:

  1、停止现在,webpack设置以及dev和build剧本仅仅是调通大抵的流程,另有许多可优化可精细精美的处所,后续完美项目的过程当中会对打包流程逐步润饰;

  2、vue百口桶在现实项目中高级用法许多,细节也许多,这里只是最简朴的用法,如若用到现实项目中,还要基于现在状况再做细化;

  3、本系列文章旨在纪录、回忆全部项目框架搭建流程,把握团体构造,许多处所须要依据现实项目再做处置惩罚;

  4、若有毛病或不当的处所,迎接指出,共同进步!

 

  选择打赏方式
微信赞助

打赏

QQ钱包

打赏

支付宝赞助

打赏

  移步手机端
【原创】从零开始搭建Electron+Vue+Webpack项目框架,一套代码,同时构建客户端、web端(二)

1、打开你手机的二维码扫描APP
2、扫描左则的二维码
3、点击扫描获得的网址
4、可以在手机端阅读此文章
未定义标签

本文来源:搜奇网

本文地址:https://www.sou7.cn/282315.html

关注我们:微信搜索“搜奇网”添加我为好友

版权声明: 本文仅代表作者个人观点,与本站无关。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。请记住本站网址https://www.sou7.cn/搜奇网。

发表评论

选填

必填

必填

选填

请拖动滑块解锁
>>