1.用脚手架搭建框架javascript
参考vue-cli2的webpack模板骨架搭建的electron和Vue结合。electron-vue是vue-cli和electron结合的项目,比单独使用vue构建起的electron项目要方便不少.(须要使用node 7或者更高的版本)官方推荐yarn做为包的管理器,能更好的处理依赖关系,并使用yarn clean 帮助减小最后的文件构建。咱们须要检查的第一项是 npm 的版本,并确保它是最新的。这个能够使用 npm-windows-upgrade
来完成。若是你使用 yarn
,则能够跳过此项检查。css
# 安装 vue-cli 和 脚手架样板代码 npm install -g vue-cli vue init simulatedgreg/electron-vue my-project # 安装依赖并运行你的程序 cd my-project yarn # 或者 npm install yarn run dev # 或者 npm run dev
2. 完成配置html
(1).在配置文件下增长muti-page.config.jsvue
const glob = require('glob'); const path = require('path'); const PAGE_PATH = path.resolve(__dirname, '../src/renderer'); const HtmlWebpackPlugin = require('html-webpack-plugin'); exports.entries = function () { /*用于匹配 pages 下一级文件夹中的 index.js 文件 */ var entryFiles = glob.sync(PAGE_PATH + '/*/main.js') var map = {} entryFiles.forEach((filePath) => { /* 下述两句代码用于取出 pages 下一级文件夹的名称 */ var entryPath = path.dirname(filePath) var filename = entryPath.substring(entryPath.lastIndexOf('\/') + 1) /* 生成对应的键值对 */ map[filename] = filePath }) return map } exports.htmlPlugin = function () { let entryHtml = glob.sync(PAGE_PATH + '/*/index.ejs') let arr = [] entryHtml.forEach((filePath) => { var entryPath = path.dirname(filePath) var filename = entryPath.substring(entryPath.lastIndexOf('\/') + 1) let conf = { template: filePath, filename: filename + `/index.html`, chunks: ['manifest', 'vendor', filename], inject: true, nodeModules: path.resolve(__dirname, '../node_modules') } if (process.env.NODE_ENV === 'production') { let productionConfig = { minify: { removeComments: true, // 移除注释 collapseWhitespace: true, // 删除空白符和换行符 removeAttributeQuotes: true // 移除属性引号 }, chunksSortMode: 'dependency' // 对引入的chunk模块进行排序 } conf = {...conf, ...productionConfig} //合并基础配置和生产环境专属配置 } arr.push(new HtmlWebpackPlugin(conf)) }) return arr }
(2)在.electron-vue文件夹下的 webpack.renderer.config.js修改,修改后以下:java
'use strict' process.env.BABEL_ENV = 'renderer' const path = require('path') const { dependencies } = require('../package.json') const webpack = require('webpack') const BabiliWebpackPlugin = require('babili-webpack-plugin') const CopyWebpackPlugin = require('copy-webpack-plugin') const MiniCssExtractPlugin = require('mini-css-extract-plugin') const HtmlWebpackPlugin = require('html-webpack-plugin') const { VueLoaderPlugin } = require('vue-loader') const {entries, htmlPlugin} = require('./muti-page.config') /** * List of node_modules to include in webpack bundle * * Required for specific packages like Vue UI libraries * that provide pure *.vue files that need compiling * https://simulatedgreg.gitbooks.io/electron-vue/content/en/webpack-configurations.html#white-listing-externals */ let whiteListedModules = ['vue'] console.log() let rendererConfig = { devtool: '#cheap-module-eval-source-map', // entry: { // renderer: path.join(__dirname, '../src/renderer/main.js') // }, entry: entries, externals: [ ...Object.keys(dependencies || {}).filter(d => !whiteListedModules.includes(d)) ], module: { rules: [ // { // test: /\.(js|vue)$/, // enforce: 'pre', // exclude: /node_modules/, // use: { // loader: 'eslint-loader', // options: { // formatter: require('eslint-friendly-formatter') // } // } // }, { test: /\.scss$/, use: ['vue-style-loader', 'css-loader', 'sass-loader'] }, { test: /\.sass$/, use: ['vue-style-loader', 'css-loader', 'sass-loader?indentedSyntax'] }, { test: /\.less$/, use: ['vue-style-loader', 'css-loader', 'less-loader'] }, { test: /\.css$/, use: ['vue-style-loader', 'css-loader'] }, { test: /\.html$/, use: 'vue-html-loader' }, { test: /\.js$/, use: 'babel-loader', exclude: /node_modules/ }, { test: /\.node$/, use: 'node-loader' }, { test: /\.vue$/, use: { loader: 'vue-loader', options: { extractCSS: process.env.NODE_ENV === 'production', loaders: { sass: 'vue-style-loader!css-loader!sass-loader?indentedSyntax=1', scss: 'vue-style-loader!css-loader!sass-loader', less: 'vue-style-loader!css-loader!less-loader' } } } }, { test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, use: { loader: 'url-loader', query: { limit: 10000, name: 'imgs/[name]--[folder].[ext]', fallback: 'file-loader', outputPath: './', publicPath: '../' } } }, { test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/, loader: 'url-loader', options: { limit: 10000, name: 'media/[name]--[folder].[ext]' } }, { test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, use: { loader: 'url-loader', query: { limit: 10000, name: 'fonts/[name]--[folder].[ext]' } } } ] }, node: { __dirname: process.env.NODE_ENV !== 'production', __filename: process.env.NODE_ENV !== 'production' }, plugins: [ new VueLoaderPlugin(), new webpack.ProvidePlugin({ $:'jquery', jQuery: 'jquery' }), new MiniCssExtractPlugin({filename: 'styles.css'}), // new HtmlWebpackPlugin({ // filename: 'index.html', // template: path.resolve(__dirname, '../src/index.ejs'), // minify: { // collapseWhitespace: true, // removeAttributeQuotes: true, // removeComments: true // }, // nodeModules: process.env.NODE_ENV !== 'production' // ? path.resolve(__dirname, '../node_modules') // : false // }), new webpack.HotModuleReplacementPlugin(), new webpack.NoEmitOnErrorsPlugin() // 注释原来的HtmlWebpackPlugin插件代码,在数组后添加.concat(htmlPlugin()) ].concat(htmlPlugin()), output: { // filename: '[name].js',修改filename的[name].js 为[name]/index.js,一、是为了将js文件和html文件归类在一块儿;二、[name].js时html访问的是绝对路径 filename: '[name]/index.js', libraryTarget: 'commonjs2', path: path.join(__dirname, '../dist/electron') }, resolve: { alias: { '@': path.join(__dirname, '../src/renderer'), 'vue$': 'vue/dist/vue.esm.js' }, extensions: ['.js', '.vue', '.json', '.css', '.node'] }, target: 'electron-renderer' } /** * Adjust rendererConfig for development settings */ if (process.env.NODE_ENV !== 'production') { rendererConfig.plugins.push( new webpack.DefinePlugin({ '__static': `"${path.join(__dirname, '../static').replace(/\\/g, '\\\\')}"` }) ) } /** * Adjust rendererConfig for production settings */ if (process.env.NODE_ENV === 'production') { rendererConfig.devtool = '' rendererConfig.plugins.push( new BabiliWebpackPlugin(), new CopyWebpackPlugin([ { from: path.join(__dirname, '../static'), to: path.join(__dirname, '../dist/electron/static'), ignore: ['.*'] } ]), new webpack.DefinePlugin({ 'process.env.NODE_ENV': '"production"' }), new webpack.LoaderOptionsPlugin({ minimize: true }) ) } module.exports = rendererConfig
(3)在src文件下增长渲染进程窗口的配置newPage.jsnode
import { BrowserWindow, ipcMain, screen } from 'electron'; let win = null; const winURL = process.env.NODE_ENV === 'development' ? 'http://localhost:9080/newPage' : `file://${__dirname}/newPage/index.html`; function createNewPageWindow() { const size = screen.getPrimaryDisplay().workAreaSize; // 获取显示器的宽高 // const winSize = win.getSize(); // 获取窗口宽高 win = new BrowserWindow({ width: size.width, height: size.height, minWidth: 500, minHeight: 130, type: 'toolbar', // 建立的窗口类型为工具栏窗口 frame: true, // 要建立无边框窗口 movable: true, // 窗口是否能够移动 show: true, // 先不让窗口显示 webPreferences: { devTools: true, // 关闭调试工具 webSecurity: true }, useContentSize: true }); // 设置窗口的位置 注意x轴要桌面的宽度 - 窗口的宽度 win.loadURL(winURL); // win.setPosition((size.width - winSize[0]) / 2, 350); // 监听渲染完成 if (process.env.NODE_ENV === 'development') { win.webContents.on('did-frame-finish-load', () => { win.webContents.once('devtools-opened', () => { // win.focus(); }); win.webContents.openDevTools(); }); } win.once('ready-to-show', () => { win.show(); }); // 监听窗口关闭 win.on('close', () => { win = null; }); global.newPage = { id: win.id }; } /** * 监听建立新窗口 */ ipcMain.on('showNewPageWindow', () => { if (win) { if (win.isVisible()) { createNewPageWindow(); } else { win.showInactive(); } } else { createNewPageWindow(); } }); /** * 监听隐藏新窗口 */ ipcMain.on('hideNewPageWindow', () => { if (win) { win.hide(); } });
(4)在主进程界面引入newPage.jsjquery
import { app, BrowserWindow } from 'electron' // eslint-disable-line /** * Set `__static` path to static files in production * https://simulatedgreg.gitbooks.io/electron-vue/content/en/using-static-assets.html */ if (process.env.NODE_ENV !== 'development') { global.__static = require('path').join(__dirname, '/static').replace(/\\/g, '\\\\') // eslint-disable-line } let mainWindow; const winURL = process.env.NODE_ENV === 'development' ? 'http://localhost:9080/main' : `file://${__dirname}/main/index.html`; function createWindow() { /** * Initial window options */ mainWindow = new BrowserWindow({ height: 563, useContentSize: true, width: 1000, webPreferences: { webSecurity: false, devTools: true }, show: false, title: 'vue-electron多界面', autoHideMenuBar: true, alwaysOnTop: true // backgroundColor: '#2e2c29' }); mainWindow.loadURL(winURL); mainWindow.once('ready-to-show', () => { mainWindow.maximize(); // 最大化 // mainWindow.show() }); mainWindow.on('closed', () => { mainWindow = null; if (process.platform !== 'darwin') { app.quit(); } }); if (process.env.NODE_ENV === 'development') { mainWindow.webContents.on('did-frame-finish-load', () => { mainWindow.webContents.once('devtools-opened', () => { // mainWindow.focus(); }); mainWindow.webContents.openDevTools(); }); } // 引入newPage.js,负责悬浮窗口内主进程和渲染进程之间的通讯 require('./newPage'); global.mainWindow = { id: mainWindow.id }; } app.on('ready', createWindow); app.on('window-all-closed', () => { if (process.platform !== 'darwin') { app.quit(); } }); app.on('activate', () => { if (mainWindow === null) { createWindow(); } }); /** * Auto Updater * * Uncomment the following code below and install `electron-updater` to * support auto updating. Code Signing with a valid certificate is required. * https://simulatedgreg.gitbooks.io/electron-vue/content/en/using-electron-builder.html#auto-updating */ /* import { autoUpdater } from 'electron-updater' autoUpdater.on('update-downloaded', () => { autoUpdater.quitAndInstall() }) app.on('ready', () => { if (process.env.NODE_ENV === 'production') autoUpdater.checkForUpdates() }) */
参考自:https://blog.csdn.net/weixin_41855143/article/details/89408218webpack