diff --git a/README.md b/README.md
index 882f96a..b43bb59 100644
--- a/README.md
+++ b/README.md
@@ -171,6 +171,10 @@ chrome-extension-cli my-extension --override-page=history // Override Histo
Creates a Panel inside developer tools.
+#### `chrome-extension-cli my-extension --no-cross-browser`
+
+The generated project will not be cross-browser compatible by default.
+
## Contributing
See the [contribution guide](CONTRIBUTING.md) and join the contributors!
diff --git a/config/webpack.common.js b/config/webpack.common.js
index 52b29a5..b4680f1 100644
--- a/config/webpack.common.js
+++ b/config/webpack.common.js
@@ -6,60 +6,86 @@ const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const PATHS = require('./paths');
-// To re-use webpack configuration across templates,
-// CLI maintains a common webpack configuration file - `webpack.common.js`.
-// Whenever user creates an extension, CLI adds `webpack.common.js` file
-// in template's `config` folder
-const common = {
- output: {
- // the build folder to output bundles and assets in.
- path: PATHS.build,
- // the filename template for entry chunks
- filename: '[name].js',
- },
- devtool: 'source-map',
- stats: {
- all: false,
- errors: true,
- builtAt: true,
- },
- module: {
- rules: [
- // Help webpack in understanding CSS files imported in .js files
- {
- test: /\.css$/,
- use: [MiniCssExtractPlugin.loader, 'css-loader'],
- },
- // Check for images imported in .js files and
- {
- test: /\.(png|jpe?g|gif)$/i,
- use: [
- {
- loader: 'file-loader',
- options: {
- outputPath: 'images',
- name: '[name].[ext]',
+module.exports = env => {
+ // To re-use webpack configuration across templates,
+ // CLI maintains a common webpack configuration file - `webpack.common.js`.
+ // Whenever user creates an extension, CLI adds `webpack.common.js` file
+ // in template's `config` folder
+ const crossBrowser = (env.CROSS_BROWSER === 'true');
+ const common = {
+ output: {
+ // the build folder to output bundles and assets in.
+ path: PATHS.build,
+ // the filename template for entry chunks
+ filename: '[name].js',
+ },
+ devtool: 'source-map',
+ stats: {
+ all: false,
+ errors: true,
+ builtAt: true,
+ },
+ module: {
+ rules: [
+ // Help webpack in understanding CSS files imported in .js files
+ {
+ test: /\.css$/,
+ use: [MiniCssExtractPlugin.loader, 'css-loader'],
+ },
+ // Check for images imported in .js files and
+ {
+ test: /\.(png|jpe?g|gif)$/i,
+ use: [
+ {
+ loader: 'file-loader',
+ options: {
+ outputPath: 'images',
+ name: '[name].[ext]',
+ },
},
- },
- ],
- },
+ ],
+ },
+ ],
+ },
+ plugins: [
+ // Print file sizes
+ new SizePlugin(),
+ // Copy static assets from `public` folder to `build` folder, except .html files
+ new CopyWebpackPlugin([
+ {
+ from: '**/*',
+ context: 'public',
+ ignore: ['*.html']
+ },
+ ]),
+ // copy static .html files from `public` folder to `build` folder, and replace the `<%= browser-polyfill %>` variable depending on config
+ new CopyWebpackPlugin([
+ {
+ from: '**/*.html',
+ context: 'public',
+ transform: (content) => {
+ const polyfill = '';
+ if(crossBrowser) {
+ return content.toString().replace('<%= browser-polyfill %>', polyfill);
+ }
+ return content.toString().replace('<%= browser-polyfill %>', '');
+ }
+ },
+ ]),
+ // Extract CSS into separate files
+ new MiniCssExtractPlugin({
+ filename: '[name].css',
+ }),
],
- },
- plugins: [
- // Print file sizes
- new SizePlugin(),
- // Copy static assets from `public` folder to `build` folder
- new CopyWebpackPlugin([
- {
- from: '**/*',
- context: 'public',
- },
- ]),
- // Extract CSS into separate files
- new MiniCssExtractPlugin({
- filename: '[name].css',
- }),
- ],
-};
+ };
-module.exports = common;
+ if(crossBrowser) {
+ // Copy browser-polyfill.js for cross browser compability
+ common.plugins.unshift(new CopyWebpackPlugin([
+ {
+ from: 'node_modules/webextension-polyfill/dist/browser-polyfill.min.js'
+ }
+ ]));
+ }
+ return common;
+}
diff --git a/index.js b/index.js
index d349726..22799fb 100755
--- a/index.js
+++ b/index.js
@@ -12,6 +12,7 @@ const packageFile = require('./package.json');
const { checkAppName, prettifyAppName } = require('./utils/name');
const generateReadme = require('./scripts/readme');
const tryGitInit = require('./scripts/git-init');
+const browserPolyfillFilename = 'browser-polyfill.min.js';
let projectName;
const OVERRIDE_PAGES = ['newtab', 'bookmarks', 'history'];
@@ -28,6 +29,7 @@ const program = new commander.Command(packageFile.name)
'override default page like New Tab, Bookmarks, or History page'
)
.option('--devtools', 'add features to Chrome Developer Tools')
+ .option('--no-cross-browser', `the generated project will not be cross-browser compatible`)
.on('--help', () => {
console.log(` Only ${chalk.green('')} is required.`);
})
@@ -90,7 +92,7 @@ function logOptionsConflictError() {
process.exit(1);
}
-function createExtension(name, { overridePage, devtools }) {
+function createExtension(name, { overridePage, devtools, crossBrowser }) {
const root = path.resolve(name);
let overridePageName;
@@ -126,8 +128,8 @@ function createExtension(name, { overridePage, devtools }) {
appPackage.scripts = {
watch:
- 'webpack --mode=development --watch --config config/webpack.config.js',
- build: 'webpack --mode=production --config config/webpack.config.js',
+ `webpack --mode=development --env.CROSS_BROWSER=${crossBrowser} --watch --config config/webpack.config.js`,
+ build: `webpack --mode=production --env.CROSS_BROWSER=${crossBrowser} --config config/webpack.config.js`,
};
// Create package file in project directory
@@ -148,7 +150,8 @@ function createExtension(name, { overridePage, devtools }) {
'size-plugin',
'mini-css-extract-plugin',
'css-loader',
- 'file-loader'
+ 'file-loader',
+ 'webextension-polyfill'
);
console.log('Installing packages. This might take a couple of minutes.');
@@ -176,7 +179,36 @@ function createExtension(name, { overridePage, devtools }) {
templateName = 'popup';
}
- fs.copySync(path.resolve(__dirname, 'templates', templateName), root);
+ const files = [];
+ fs.copySync(path.resolve(__dirname, 'templates', templateName), root, {
+ filter: filename => {
+ const endsWithNoCrossbrowser = /\.nocrossbrowser\.js$/.test(filename); // determine if filename ends with '.nocrossbrowser.js'
+ if(!/\.js$/.test(filename)) return true; // copy all files that aren't .js files
+ if(/webpack\.config\.js$/.test(filename)) return true; // explcitly copy webpack.config.js all the time
+ if(!crossBrowser && endsWithNoCrossbrowser) {
+ files.push(filename);
+ return true;
+ } else if(crossBrowser && !endsWithNoCrossbrowser) {
+ return true;
+ } else if(!crossBrowser && !endsWithNoCrossbrowser) {
+ const parsedPath = path.parse(filename);
+ const pathWithCrossbrowser = path.resolve(parsedPath.dir, parsedPath.name, '.nocrossbrowser', parsedPath.ext);
+ return !fs.pathExists(pathWithCrossbrowser);
+ }
+ return false;
+ }
+ });
+
+ // if the webextenstion support is not enabled, we need to copy the template files with .nocrosbbrowser.js ending
+ // but after that, these files are renamed and the .nocrosbbrowser extension is removed
+ if(!crossBrowser) {
+ files.forEach(file => {
+ const { base } = path.parse(file);
+ let srcPath = path.resolve(root, 'src', base);
+ let destPath = path.resolve(root, 'src', base.replace('.nocrossbrowser', ''));
+ fs.moveSync(srcPath, destPath);
+ });
+ }
// Copy common webpack configuration file
fs.copySync(path.resolve(__dirname, 'config'), path.join(root, 'config'));
@@ -241,6 +273,13 @@ function createExtension(name, { overridePage, devtools }) {
};
}
+ if(crossBrowser) {
+ appManifest.background.scripts = [browserPolyfillFilename, ...appManifest.background.scripts];
+ if(appManifest.content_scripts) {
+ appManifest.content_scripts.forEach(i => i.js.unshift(browserPolyfillFilename));
+ }
+ }
+
// Create manifest file in project directory
fs.writeFileSync(
path.join(root, 'public', 'manifest.json'),
@@ -284,4 +323,5 @@ function createExtension(name, { overridePage, devtools }) {
createExtension(projectName, {
overridePage: program.overridePage,
devtools: program.devtools,
+ crossBrowser: program.crossBrowser
});
diff --git a/package-lock.json b/package-lock.json
index 10a84a8..32b9e70 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
{
"name": "chrome-extension-cli",
- "version": "0.1.0",
+ "version": "0.2.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@@ -138,6 +138,12 @@
"builtins": "^1.0.3"
}
},
+ "webextension-polyfill": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/webextension-polyfill/-/webextension-polyfill-0.5.0.tgz",
+ "integrity": "sha512-aFrl38x43t1bTboX/paCT8I97+idzX/TY0+fuM52hrIkCpYfROEF9kSn0BXuEIi3J9LTYt2ZZKkhx9NB1qF3nA==",
+ "dev": true
+ },
"which": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
diff --git a/package.json b/package.json
index cea496e..89b7618 100644
--- a/package.json
+++ b/package.json
@@ -43,6 +43,7 @@
"validate-npm-package-name": "^3.0.0"
},
"devDependencies": {
- "prettier": "^1.18.2"
+ "prettier": "^1.18.2",
+ "webextension-polyfill": "^0.5.0"
}
}
diff --git a/templates/devtools/config/webpack.config.js b/templates/devtools/config/webpack.config.js
index 158346f..ef2d025 100644
--- a/templates/devtools/config/webpack.config.js
+++ b/templates/devtools/config/webpack.config.js
@@ -2,16 +2,16 @@
const merge = require('webpack-merge');
-const common = require('./webpack.common.js');
+const getCommonConfig = require('./webpack.common.js');
const PATHS = require('./paths');
-// Merge webpack configuration files
-const config = merge(common, {
- entry: {
- devtools: PATHS.src + '/devtools.js',
- panel: PATHS.src + '/panel.js',
- background: PATHS.src + '/background.js',
- },
-});
-
-module.exports = config;
+module.exports = env => {
+ // Merge webpack configuration files
+ return merge(getCommonConfig(env), {
+ entry: {
+ devtools: PATHS.src + '/devtools.js',
+ panel: PATHS.src + '/panel.js',
+ background: PATHS.src + '/background.js',
+ },
+ });
+}
diff --git a/templates/devtools/public/devtools.html b/templates/devtools/public/devtools.html
index 02c9464..aaaaad8 100644
--- a/templates/devtools/public/devtools.html
+++ b/templates/devtools/public/devtools.html
@@ -5,6 +5,7 @@
Chrome DevTools
+ <%= browser-polyfill %>