Skip to content

Commit

Permalink
feat(build): only include external deps, fixes #223
Browse files Browse the repository at this point in the history
  • Loading branch information
nklayman committed Mar 23, 2019
1 parent f61d2b7 commit cd3d9ab
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 11 deletions.
47 changes: 39 additions & 8 deletions __tests__/commands.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const path = require('path')
const execa = require('execa')
const portfinder = require('portfinder')
const Application = require('spectron').Application
const { chainWebpack } = require('../lib/webpackConfig')
const { chainWebpack, getExternals } = require('../lib/webpackConfig')
// #endregion

// #region Mocks
Expand Down Expand Up @@ -47,6 +47,12 @@ jest.mock('@vue/cli-service/lib/commands/serve', () => ({
serve: jest.fn().mockResolvedValue({ url: 'serveUrl' })
}))
jest.mock('electron-builder', () => ({ build: jest.fn().mockResolvedValue() }))
// Mock package.json
fs.readFileSync.mockReturnValue(
JSON.stringify({
dependencies: {}
})
)
const mockWait = jest.fn().mockResolvedValue()
const mockStart = jest.fn()
jest.mock('spectron', () => ({
Expand Down Expand Up @@ -204,14 +210,12 @@ describe('electron:build', () => {
fs.existsSync.mockReturnValueOnce(true)
await runCommand('electron:build')
// css/fonts folder was created
expect(fs.ensureDirSync.mock.calls[2][0]).toBe(
expect(fs.ensureDirSync).toBeCalledWith(
'projectPath/dist_electron/bundled/css/fonts'
)
// fonts was copied to css/fonts
expect(fs.copySync.mock.calls[1][0]).toBe(
'projectPath/dist_electron/bundled/fonts'
)
expect(fs.copySync.mock.calls[1][1]).toBe(
expect(fs.copySync).toBeCalledWith(
'projectPath/dist_electron/bundled/fonts',
'projectPath/dist_electron/bundled/css/fonts'
)
})
Expand Down Expand Up @@ -337,15 +341,42 @@ describe('electron:build', () => {
}
})
expect(fs.writeFileSync).toBeCalledWith(
`dist_electron${path.sep}bundled${path.sep}legacy-assets-index.html.json`,
`dist_electron${path.sep}bundled${
path.sep
}legacy-assets-index.html.json`,
'[]'
)
expect(fs.writeFileSync).toBeCalledWith(
`dist_electron${path.sep}bundled${path.sep}legacy-assets-subpage.html.json`,
`dist_electron${path.sep}bundled${
path.sep
}legacy-assets-subpage.html.json`,
'[]'
)
}
)

test('Only external deps are included in the package.json', async () => {
fs.readFileSync.mockReturnValueOnce(
JSON.stringify({
dependencies: {
nonExternal: '^0.0.1',
external: '^0.0.1'
}
})
)
getExternals.mockReturnValueOnce({ external: 'require("external")' })

await runCommand('electron:build')

expect(fs.writeFileSync).toBeCalledWith(
`dist_electron${path.sep}bundled${path.sep}package.json`,
JSON.stringify({
dependencies: {
external: '^0.0.1'
}
})
)
})
})

describe('electron:serve', () => {
Expand Down
17 changes: 14 additions & 3 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -130,9 +130,20 @@ module.exports = (api, options) => {
// Build the render process with the custom args
await api.service.run('build', vueArgs)
// Copy package.json to output dir
fs.copySync(
api.resolve('./package.json'),
`${outputDir}/bundled/package.json`
const pkg = JSON.parse(
fs.readFileSync(api.resolve('./package.json'), 'utf8')
)
const externals = getExternals(api, pluginOptions)
// https://github.com/nklayman/vue-cli-plugin-electron-builder/issues/223
// Strip non-externals from dependencies so they won't be copied into app.asar
Object.keys(pkg.dependencies).forEach(dependency => {

This comment has been minimized.

Copy link
@TemaSM

TemaSM Jul 19, 2019

@nklayman this line produces error in situation when package.json has no dependencies

(node:33984) UnhandledPromiseRejectionWarning: TypeError: Cannot convert undefined or null to object
    at Function.keys (<anonymous>)
    at Promise (D:\<PROJECT_DIR>\node_modules\vue-cli-plugin-electron-builder\index.js:139:18)
    at process._tickCallback (internal/process/next_tick.js:68:7)

It's a good practice (for Electron with Webpack) to move all dependencies to devDependencies, because webpack produces dist files of our app as bundle.
This practice prevents bloating app in size by electron-builder which includes every single dependency stated in dependencies section of package.json, including nested dependencies, even if they not used at all.
Detailed info may be found here: https://github.com/michalzaq12/electron-nuxt#dependencies-vs-devdependencies

This comment has been minimized.

Copy link
@nklayman

nklayman Jul 19, 2019

Author Owner

With this plugin, there is no need to move your deps. Since it knows the list of deps you need to require at runtime, it removes all others from the dependencies section of your package.json. This means you can keep your dependency structure the same without adding unnecessary code to your built app. You can see this is action in the 2 lines below the one you commented 😄.

This comment has been minimized.

Copy link
@TemaSM

TemaSM Jul 19, 2019

Hah, that's make sense. Thank for reply & info.
It would be great to add this info to docs (if it still has no such info, cause I didn't find).
Thanks for all of you work, keep going please 👍

if (!Object.keys(externals).includes(dependency)) {
delete pkg.dependencies[dependency]
}
})
fs.writeFileSync(
`${outputDir}/bundled/package.json`,
JSON.stringify(pkg, 2)
)
// Prevent electron-builder from installing app deps
fs.ensureDirSync(`${outputDir}/bundled/node_modules`)
Expand Down

0 comments on commit cd3d9ab

Please sign in to comment.