• 【原創】從零開始搭建Electron+Vue+Webpack項目框架(六)Electron打包,同時構建客戶端和web端

    導航:

    (一)Electron跑起來
    (二)從零搭建Vue全家桶+webpack項目框架
    (三)Electron+Vue+Webpack,聯合調試整個項目
    (四)Electron配置潤色
    (五)預加載及自動更新
    (六)構建、發布整個項目(包括client和web)

    摘要:整個項目就剩最后一哆嗦了,但僅僅是當作demo模版來說,實際項目的話,還有很多需要細化的地方。項目完整代碼:https://github.com/luohao8023/electron-vue-template,隨博客更新。

    一、打包客戶端

    首先是要改一下build.js,把上篇文章沒做的事兒給做了。

    上篇文章已經構建出了可執行文件目錄app,這次我們要做的就是使用electron-builder把app目錄打包為安裝包。

    在之前的基礎上引入electron-builder,然后對app目錄進行打包:

    const builder = require('electron-builder');
    
    // 在所有的打包邏輯執行完成之后,確認已經正確生成了app目錄
    builder.build().then(() => {
        del(['./pack/*.yaml', './pack/*.blockmap']);
        // 為了方便,打包完成之后我們打開文件管理器
        openFileManager();
    });
    
    function openFileManager() {
        // 打開文件管理器
        let dirPath = path.join(__dirname, '..', 'pack');
        if (process.platform === 'darwin') {
            spawn('open', [dirPath]);
        } else if (process.platform === 'win32') {
            spawn('explorer', [dirPath]);
        } else if (process.platform === 'linux') {
            spawn('nautilus', [dirPath]);
        }
    }

    然后自信滿滿的開始打包。。。。

    報錯了,說是什么描述缺失,icon沒有設置啥的,就是打包的時候沒有配置唄,去看下package.json文件,果然是少了build字段,package.json文件中的build字段就是有關打包的配置,一些必要的配置項還是要填的。

    在package.json中增加build字段:

    "build": {
        "asar": true,
        "productName": "Electron+vue+webpack模板",
        "appId": "com.electron.template",
        "copyright": "Copyright © template",
        "directories": {
            "output": "pack"
        },
        "files": [
            "app/**"
        ],
        "mac": {
            "identity": "com.electron.templat",
            "target": [
                "dmg"
            ],
            "artifactName": "${productName}.${ext}",
            "icon": "main/favicon/favicon.icns"
        },
        "dmg": {
            "title": "${productName}",
            "artifactName": "${productName}.${ext}",
            "icon": "main/favicon/favicon.icns"
        },
        "win": {
            "legalTrademarks": "Copyright © template",
            "publisherName": "electron",
            "requestedExecutionLevel": "highestAvailable",
            "target": [
                {
                    "target": "nsis",
                    "arch": [
                        "ia32"
                    ]
                }
            ],
            "artifactName": "${productName}.${ext}",
            "icon": "main/favicon/favicon.ico"
        },
        "nsis": {
            "oneClick": false,
            "allowToChangeInstallationDirectory": true,
            "perMachine": true,
            "allowElevation": true,
            "artifactName": "${productName}-安裝包-V${version}.${ext}",
            "runAfterFinish": true,
            "shortcutName": "Electron+vue+webpack-template"
        }
      },

    現在我們來挨個解讀一下各個配置項都是什么意思,當然還有很多其他配置,這里不再額外介紹了。

    asar:是否打包為asar文件,設置為true的話,相當于給你的代碼加密了一下,直接就是個.asar的文件,具體內容需要解密了之后才能看到;設置為false的話,不對你的代碼進行加密處理,也就是用戶安裝你的程序之后,找到安裝目錄,就能直接看到源碼,目錄結構跟你開發的時候是一樣的,不太安全,建議設置為true;

    productName:你的應用名稱,比如會顯示在安裝程序的標題處,以及安裝完成后的應用程序目錄里;
    appId:你程序的唯一id,比如綁定到某第三方平臺或應用市場,一般會需要這個,我是沒有,隨便填的;
    copyright:按照網站的copyright來理解就好啦,如果你的程序不需要發不到各大市場的話,這個內容可以忽略;
    directories:它下面還有其他屬性,這里我們只填了ouptut選項,就是打包輸出目錄,我們這里填了pack文件夾;
    files:需要打包哪些內容,就是你的源代碼,我們這里填的"app/*",就是app目錄下的所有內容;
     
    上面都是一些基礎的內容,下面介紹一下針對不同平臺的配置:
    mac:
    identity:這個我不是特別清楚,看名字應該是表明開發者或者軟件身份的東西;
    target:你要打包成什么格式的安裝包,這里填的是dmg,可以填多個;
    artifactName:生成的可執行文件的名稱;
    icon:應用圖標,顯示在桌面快捷方式或者系統托盤;
    針對dmg的單獨配置這里就不說了,因為mac選項的target屬性可以多填,我們填了dmg,就對dmg做了單獨的配置,也可以忽略;
    win:
    legalTrademarks:合法商標。。。。。。
    publisherName:發行商類似的意思;
    requestedExecutionLevel:應用程序需要的權限,我們這里填的是highestAvailable,就是當前用戶允許的最高權限,你如果是管理員用戶在使用,那就是管理員權限,如果是普通用戶在使用那就是普通管理員權限。設置為最高權限可以解決一些問題,比如對c盤的一些文件進行操作等。但是請注意一點,如果你的程序是以管理員身份運行的,但是你又想實現從桌面往應用程序中拖動文件的功能,這是不行的,因為文件管理器的權限是低于管理員的,windows上無法從低權限處往高權限處拖動文件,這點還是要注意一下;
    target:目標平臺,我們選32位,并且使用nsis打包;
    artifactName:可執行文件名稱;
    icon:應用圖標;
    nsis:
    因為electron-builder是基于nsis打包的(有興趣的可以了解一下nsis),所以這里提供了一些基礎配置:
    oneClick:不是點擊一次,也不是單例什么的,這里是一鍵安裝的意思,設置為true的話,只要雙擊打開安裝包,程序會自動安裝并運行;建議設置為false,讓用戶點擊下一步、下一步來安裝;
    allowToChangeInstallationDirectory:是否允許修改安裝目錄,默認為false;
    perMachine:每臺機器是否只允許安裝一個程序,如果已安裝,再次安裝的時候,會要求用戶先刪除之前的程序;
    allowElevation:允許請求提升(權限),如果設置為false,用戶必須重啟程序才能安裝提升了權限的安裝程序;
    artifactName:安裝包名稱;
    runAfterFinish:安裝完成是否運行程序;
    shortcutName:快捷方式名稱
    這是模版里用到的所有屬性,解釋的也不一定對。當然還有很多其他的配置項,感興趣的可以搜一下了解了解,說不定某個小小的配置就能解決你一個大問題呢。
     
    好了,說了這么多,現在接著運行打包命令吧,看看啥情況:
    (node:96470) UnhandledPromiseRejectionWarning: Error: Application entry file "index.js" in the "/Volumes/SHARE/projects/github/electron-vue-template/pack/mac/Electron+vue+webpack模板.app/Contents/Resources/app.asar" does not exist. Seems like a wrong configuration.

    還是有錯啊,說的很詳細,說是程序入口文件index.js不存在,我們看一下:

      "name": "electron-vue-template",
      "version": "1.0.0",
      "description": "electron-vue-template",
      "main": "index.js",
      "scripts": {
        "dev": "node ./builder/dev.js",
        "build": "node ./builder/build.js"
      },

    main字段就是程序入口,我們寫的是index.js,看下代碼目錄,我們的主進程入口是main.js,那就改一下吧,把index.js改為main.js,接著運行打包命令:

    還是出錯呦,入口文件找不到,這個問題還真想來好大一會兒,感覺沒有錯啊,名稱也修改來,就是main.js啊,又瞅了眼代碼目錄才恍然大悟,這不陰溝里翻船嘛,通常情況下main.js是在工程根目錄的,但是我們規劃完工程目錄之后,把main.js給打包到app目錄下了,所以入口字段應該填"app/main.js",接著運行打包命令,這次終于成功了,看下pack文件夾中生成的文件:

    第一個dmg文件就是mac的安裝包,第二個yml文件記錄了程序的一些基本信息,mac文件夾下是一個免安裝的可執行程序,最后一個就是我們壓縮出來的小版本,windows下跟這個目錄不一樣。

    先不著急安裝,打開mac文件夾下的可執行程序,可以直接打開我們的程序,打開之后懵了,一片空白啊,啥東西也沒有,趕緊找找原因。

    打開app目錄發現,沒有生成update.html,經排查發現,上次提交的代碼有個地方寫錯了,拼錯了個單詞:

    Promise.all([buildPreload(), buildRender()]).then(resolve => {
        resolve.forEach(log => {
            console.log('打包輸出===>', log);
        });
        const outpath = path.join(__dirname, '../pack/');
        try {
            fs.mkdirSync(outpath);
        } catch(e) {
            console.log('已創建pack文件夾', e);
        }
        console.log('打包渲染進程完畢!壓縮小版本!');
        const zipPath = renderConfig.output.path;
        const fileName = setup.versionType + '-' + setup.version.join('.');
        const filePath = path.join(zipPath, `../pack/${fileName}.zip`);
        compress(zipPath, filePath, 7 , (type,msg) => {
            if (type === 'error'){
                Promise.reject('壓縮文件時出錯:' + msg);
            } else {
                console.log(`壓縮包大小為:${(msg / 1024 / 1024).toFixed(2)}MB`);
            }
        });
        Promise.all([buildMain(), buildUpdate()]).then(resplve => {
            resolve.forEach(log => {
                console.log('打包輸出===>', log)
            });
            builder.build().then(() => {
                del(['./pack/*.yaml', './pack/*.blockmap']);
                openFileManager();
            });
        }).catch(err => {
            console.error('打包【main】-【update】錯誤輸出===>', err);
            process.exit(2);
        });
    }).catch(err => {
        console.error('打包【preload】-【render】出錯,輸出===>', err);
        process.exit(1);
    });

    看一下,第二個Promise.all.then中,參數寫成了resplve,而在打印log的時候用的是resolve,偏偏上面有resovle,所以也沒報錯,但是第二次promise的log就全被吃了,趕緊改回來,再跑一下,果然有個錯誤:

    打包輸出===> ModuleNotFoundError: Module not found: Error: Can't resolve 'css-loader' in '/Volumes/SHARE/projects/github/electron-vue-template':undefined

    沒有css-loader,那就裝一個:

    打包輸出===> ModuleNotFoundError: Module not found: Error: Can't resolve 'less-loader' in '/Volumes/SHARE/projects/github/electron-vue-template':undefined

    又說沒有less-loader,再裝一個,運行命令,看到app目錄下生成了update.html,這下應該沒問題了吧。

    打開mac文件夾下的免安裝文件,程序啟動后跟我們本地調試的效果是一樣的,再使用安裝包安裝一下,安裝完成打開后也是正常的。

    好啦,打包客戶端就說到這兒了,下面說一下怎么使用同一套代碼打包web端。

    二、打包web端

    這里建議把打包web端的邏輯單獨拆出來,網站代碼是同一套,但是打包邏輯是兩套

    dev的邏輯就是起個devServer返回html文件就行了,不再多說。

    而打包的話是針對單頁面的,只會生成一個html文件,如果相針對每個路由都生成一個html文件,這里提供下思路:

    引入路由文件,遍歷路由,拿到路徑,針對每個路徑,實例化一個HtmlWebpackPlugin,即可生成一個html文件:

    webpackDevConfig.plugins.push(new HtmlWebpackPlugin({
        template: './src/index.ejs',
        filename: `.${routerPah}`,
        title: "加載中...",
        inject: false,
        hash: true,
        minify: false,
        cache: false
    }))

    在package.js中增加啟動命令:

      "scripts": {
        "dev": "node ./buildClient/dev.js",
        "devweb": "node ./buildWeb/dev.js",
        "build": "node ./buildClient/build.js",
        "buildweb": "node ./buildWeb/build.js"
      }

    分別調試和打包客戶端、web端。

    這篇文章端內容就到這里了,具體的邏輯還是要去看代碼的。針對這套邏輯我們其實有已經上線了的產品的,很多細化的東西也有,但是不便拿出來說,也不好做成demo。模板中可能會有些冗余代碼,就是之前的邏輯沒有刪除干凈,自行優化就好了。

    有什么問題歡迎留言討論。項目完整代碼:https://github.com/luohao8023/electron-vue-template

    posted @ 2020-03-01 14:58  羅知晏  閱讀(...)  評論(...編輯  收藏
    贵州快三平台贵州快三主页贵州快三网站贵州快三官网贵州快三娱乐贵州快三开户贵州快三注册贵州快三是真的吗贵州快三登入贵州快三快三贵州快三时时彩贵州快三手机app下载贵州快三开奖 鸡西市 | 灌云县 | 华容县 | 大厂 | 鹤庆县 | 玉龙 | 堆龙德庆县 | 莱芜市 | 定远县 | 正定县 | 天全县 | 锡林浩特市 | 射阳县 | 福泉市 | 公主岭市 | 定边县 | 内乡县 | 云龙县 | 威宁 | 无极县 | 凤台县 | 获嘉县 | 措美县 | 祁连县 | 宣武区 | 伊金霍洛旗 | 台山市 | 商丘市 | 当涂县 | 山西省 | 和政县 | 定安县 | 罗定市 | 拜泉县 | 阿克陶县 | 同仁县 | 乡城县 | 凉城县 | 古蔺县 | 突泉县 | 汤阴县 | 策勒县 | 抚远县 | 凤凰县 | 九龙城区 | 瑞安市 | 巧家县 | 锡林郭勒盟 | 临桂县 | 尼勒克县 | 屯留县 | 徐汇区 | 安庆市 | 濉溪县 | 桓台县 | 上饶县 | 宁陵县 | 乌海市 | 武乡县 | 沙湾县 | 迁西县 | 景洪市 | 南昌县 | 长阳 | 万安县 | 焉耆 | 新绛县 | 贵港市 | 廊坊市 | 萍乡市 | 南岸区 | 金昌市 | 德惠市 | 镇平县 | 珠海市 | 桂东县 | 招远市 | 邳州市 | 绥滨县 | 邢台市 | 镇沅 | 紫金县 | 邵武市 | 太谷县 | 大荔县 | 建始县 | 黑山县 | 安西县 | 汝州市 | 宁夏 | 应用必备 | 年辖:市辖区 | 镇坪县 | 东宁县 | 五华县 | 昂仁县 | 裕民县 | 栾城县 | 金坛市 | 福清市 | 长垣县 | 黄梅县 | 博白县 | 蒙山县 | 广州市 | 长垣县 | 旌德县 | 衡水市 | 靖州 | 乐业县 | 南乐县 | 兴和县 | 镇雄县 | 颍上县 | 苗栗县 | 涟源市 | 深州市 | 新蔡县 | 黔东 | 如皋市 | 白玉县 | 东城区 | 浮梁县 | 安顺市 | 阿拉善右旗 | 岳阳市 | 合川市 | 合江县 | 石屏县 | 乐都县 | 潼关县 | 绥阳县 | 邛崃市 | 竹溪县 | 福清市 | 杭锦后旗 | 棋牌 | 楚雄市 | 确山县 | 综艺 | 阳新县 | 嘉义县 | 苍山县 | 台北县 | 临安市 | 昌宁县 | 蒙阴县 | 元谋县 | 克什克腾旗 | 阳江市 | 荃湾区 | 鞍山市 | 南丰县 | 六盘水市 | 体育 | 通化市 | 含山县 | 阜宁县 | 宿松县 | 凌源市 | 长治市 | 聂荣县 | 肇庆市 | 常熟市 | 西吉县 | 平顶山市 | 金华市 | 奎屯市 | 宁都县 | 柯坪县 | 盐城市 | 枝江市 | 海原县 | 杭锦后旗 | 海口市 | 巨鹿县 | 阳春市 | 布拖县 | 静宁县 | 阿克苏市 | 襄汾县 | 阿尔山市 | 青田县 | 顺昌县 | 台前县 | 乐安县 | 连云港市 | 五大连池市 | 宜阳县 | 丽水市 | 密云县 | 万山特区 | 陇西县 | 怀集县 | 临泉县 | 青河县 | 南乐县 | 镇巴县 | 屏南县 | 琼结县 | 永清县 | 高安市 | 边坝县 | 天水市 | 山丹县 | 定西市 | 金沙县 |