Skip to content

Commit 691e0d2

Browse files
authored
Merge pull request #5 from adambullmer/prod-build-keys
Prod build keys Fixed #4
2 parents e9d0140 + f178c77 commit 691e0d2

File tree

7 files changed

+220
-32
lines changed

7 files changed

+220
-32
lines changed

README.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,13 @@ This can be added to your vuejs project by one of the following methods:
4646
## Usage
4747
Running the Livereload server.
4848
This will build and write to the local `dist` directory.
49+
This plugin will respect the `outputDir` setting, however it cannot read into passed CLI args, so if you require a custom output dir, be sure to add it in your `vue.config.js` file.
4950
You can then add this as an unpacked plugin to your browser, and will continue to update as you make changes.
5051
**NOTE:** you cannot get HMR support in the popup window, however, closing and reopening will refresh your content.
5152

5253
```sh
53-
yarn ext-serve
54+
yarn serve
55+
yarn build
5456
```
5557

5658

@@ -62,15 +64,14 @@ yarn test
6264
```
6365

6466
## Roadmap
65-
- Add generators for background.js, popup, vuex, and vue-router stuff. (Make startup a breeze)
6667
- Add some generator options for other pieces of browser extensions. This includes scaffolding the components/dirs, and registering the build options into the build time hooks.
6768
- Dev Tools
6869
- Dedicated extension pages
6970
- Options Pages
7071
- Content scripts
71-
- Add zipping to the bundle for production builds
7272
- More configurability in scaffolding, like Kocal/vue-web-extension does
7373
- A preset
74+
- Key Generation
7475

7576
## Credits
7677
- [https://github.com/Kocal/vue-web-extension](https://github.com/Kocal/vue-web-extension) For inspiration on app and build structure

generator/index.js

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,18 @@
1+
const fs = require('fs')
2+
const gitignoreSnippet = `
3+
# Vue Browser Extension Output
4+
*.pem
5+
*.pub
6+
*.zip
7+
/dist-zip
8+
`
9+
110
module.exports = (api, { config }) => {
211
const eslintConfig = { env: { webextensions: true } }
312
const pkg = {
13+
private: true,
414
scripts: {
5-
'ext-serve': 'vue-cli-service ext-serve --mode development'
15+
'serve': 'vue-cli-service build --mode development --watch'
616
},
717
dependencies: {
818
'vue-router': '^3.0.1',
@@ -17,4 +27,9 @@ module.exports = (api, { config }) => {
1727

1828
api.extendPackage(pkg)
1929
api.render('./template')
30+
31+
api.onCreateComplete(() => {
32+
const gitignore = fs.readFileSync(api.resolve('./.gitignore'), 'utf8')
33+
fs.writeFileSync(api.resolve('./.gitignore'), gitignore + gitignoreSnippet)
34+
})
2035
}

index.js

Lines changed: 47 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,70 @@
11
const path = require('path')
2-
const { log } = require('@vue/cli-shared-utils')
2+
const fs = require('fs')
3+
const { exec } = require('child_process')
4+
const logger = require('@vue/cli-shared-utils')
35
const CopyWebpackPlugin = require('copy-webpack-plugin')
46
const ChromeExtensionReloader = require('webpack-chrome-extension-reloader')
57
const WebpackShellPlugin = require('webpack-shell-plugin-next')
68
const HtmlWebpackPlugin = require('html-webpack-plugin')
7-
const { name, version } = require(path.join(process.cwd(), 'package.json'))
9+
10+
const appRootPath = process.cwd()
811

912
module.exports = (api) => {
10-
api.configureWebpack(webpackConfig => {
13+
const { name, version } = require(path.join(appRootPath, 'package.json'))
14+
const isDevelopment = api.service.mode === 'development'
15+
const isProduction = api.service.mode === 'production'
16+
const outputDir = api.resolve(api.service.projectOptions.outputDir || 'dist')
17+
const packageScript = isProduction ? 'build-zip.js' : 'remove-evals.js'
18+
19+
api.configureWebpack((webpackConfig) => {
1120
webpackConfig.output.filename = '[name].js'
1221
webpackConfig.output.chunkFilename = 'js/[id].[name].js?[hash:8]'
1322

1423
delete webpackConfig.entry.app
1524
webpackConfig.entry.background = './src/background.js'
1625
webpackConfig.entry['popup/popup'] = './src/popup/popup.js'
1726

27+
if (isProduction) {
28+
webpackConfig.plugins.push(new CopyWebpackPlugin([{ from: './key.pem', to: 'key.pem' }]))
29+
}
30+
1831
webpackConfig.plugins.push(new CopyWebpackPlugin([
1932
{ from: './src/icons', to: 'icons/[name].[ext]', ignore: ['icon.xcf'] },
2033
{
2134
from: './src/manifest.json',
2235
to: 'manifest.json',
2336
transform: (content) => {
24-
const jsonContent = JSON.parse(content)
25-
jsonContent.version = version
37+
return new Promise((resolve, reject) => {
38+
const jsonContent = JSON.parse(content)
39+
jsonContent.version = version
2640

27-
if (process.env.NODE_ENV === 'development') {
28-
jsonContent['content_security_policy'] = "script-src 'self' 'unsafe-eval'; object-src 'self'"
29-
}
41+
if (isProduction) {
42+
return resolve(JSON.stringify(jsonContent, null, 2))
43+
}
44+
45+
jsonContent.content_security_policy = "script-src 'self' 'unsafe-eval'; object-src 'self'"
3046

31-
return JSON.stringify(jsonContent, null, 2)
47+
try {
48+
const keyfile = path.join(appRootPath, 'key.pem')
49+
fs.statSync(keyfile)
50+
51+
return exec(`openssl rsa -in ${keyfile} -pubout -outform DER | openssl base64 -A`, (error, stdout) => {
52+
if (error) {
53+
// node couldn't execute the command
54+
reject(error)
55+
}
56+
57+
jsonContent.key = stdout
58+
resolve(JSON.stringify(jsonContent, null, 2))
59+
})
60+
} catch (error) {
61+
if (isProduction) {
62+
logger.error('no key.pem file found. You cannot publish to the chrome store without one. If this is your first publish, chrome will make a key for you, and you can ignore this message')
63+
} else {
64+
logger.warn('No key.pem file found. This is fine for dev, however you may have problems publishing without one')
65+
}
66+
}
67+
})
3268
}
3369
}
3470
]))
@@ -44,16 +80,15 @@ module.exports = (api) => {
4480
chunks: ['popup/popup', 'chunk-vendors']
4581
}))
4682

47-
const scriptPath = path.join(__dirname, 'scripts/remove-evals.js')
4883
webpackConfig.plugins.push(new WebpackShellPlugin({
4984
onBuildExit: {
50-
scripts: [`node ${scriptPath}`],
85+
scripts: [`node ${path.join(__dirname, 'scripts', packageScript)} ${outputDir}`],
5186
blocking: true,
5287
parallel: false
5388
}
5489
}))
5590

56-
if (process.env.NODE_ENV === 'development') {
91+
if (isDevelopment) {
5792
webpackConfig.plugins = (webpackConfig.plugins || []).concat([
5893
new ChromeExtensionReloader({
5994
entries: {
@@ -63,16 +98,4 @@ module.exports = (api) => {
6398
])
6499
}
65100
})
66-
67-
api.registerCommand('ext-serve', {
68-
description: 'Builds and watches the project, writing the files to the output directory'
69-
}, (...args) => {
70-
log('Starting webpack in watch mode...')
71-
72-
api.configureWebpack((webpackConfig) => {
73-
webpackConfig.watch = true
74-
})
75-
76-
api.service.run('build', ...args)
77-
})
78101
}

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "vue-cli-plugin-browser-extension",
3-
"version": "0.3.3",
3+
"version": "0.4.0",
44
"description": "Browser extension development plugin for vue-cli 3.0",
55
"main": "index.js",
66
"scripts": {
@@ -29,6 +29,7 @@
2929
"html-webpack-plugin": "^3.2.0",
3030
"webpack": "^4.16.0",
3131
"webpack-chrome-extension-reloader": "^0.8.3",
32-
"webpack-shell-plugin-next": "https://github.com/adambullmer/webpack-shell-plugin-next.git"
32+
"webpack-shell-plugin-next": "https://github.com/adambullmer/webpack-shell-plugin-next.git",
33+
"zip-folder": "^1.0.0"
3334
}
3435
}

scripts/build-zip.js

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#!/usr/bin/env node
2+
3+
const fs = require('fs')
4+
const path = require('path')
5+
const zipFolder = require('zip-folder')
6+
7+
const appRootPath = process.cwd()
8+
const DEST_DIR = process.argv[2]
9+
const DEST_ZIP_DIR = path.join(appRootPath, `${DEST_DIR}-zip`)
10+
const { name, version } = require(path.join(appRootPath, 'package.json'))
11+
12+
const makeDestZipDirIfNotExists = () => {
13+
if (!fs.existsSync(DEST_ZIP_DIR)) {
14+
fs.mkdirSync(DEST_ZIP_DIR)
15+
}
16+
}
17+
18+
const buildZip = (src, dist, zipFilename) => {
19+
console.info(`Building ${zipFilename}...`)
20+
21+
return new Promise((resolve, reject) => {
22+
zipFolder(src, path.join(dist, zipFilename), (err) => {
23+
if (err) {
24+
reject(err)
25+
} else {
26+
resolve()
27+
}
28+
})
29+
})
30+
}
31+
32+
const main = () => {
33+
const zipFilename = `${name}-v${version}.zip`
34+
35+
makeDestZipDirIfNotExists()
36+
37+
buildZip(DEST_DIR, DEST_ZIP_DIR, zipFilename)
38+
.then(() => console.info('OK'))
39+
.catch(console.err)
40+
}
41+
42+
main()

scripts/remove-evals.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
const path = require('path')
44
const fs = require('fs')
5-
const BUNDLE_DIR = 'dist'
5+
const BUNDLE_DIR = process.argv[2]
66
const bundles = [
77
'background.js',
88
'popup/popup.js'

0 commit comments

Comments
 (0)