Browse Source

fix: update build scripts

Gerald 8 years ago
parent
commit
51675777da

+ 34 - 123
gulpfile.js

@@ -1,132 +1,58 @@
 const del = require('del');
 const gulp = require('gulp');
+const gutil = require('gulp-util');
 const concat = require('gulp-concat');
 const merge2 = require('merge2');
 const postcss = require('gulp-postcss');
 const gulpFilter = require('gulp-filter');
-const eslint = require('gulp-eslint');
 const uglify = require('gulp-uglify');
 const svgSprite = require('gulp-svg-sprite');
-const definePack = require('define-commonjs/pack/gulp');
-const templateCache = require('./scripts/templateCache');
+const webpack = require('webpack');
 const i18n = require('./scripts/i18n');
-const wrap = require('./scripts/wrap');
 const json = require('./scripts/json');
 const pkg = require('./package.json');
 const isProd = process.env.NODE_ENV === 'production';
+const webpackConfig = require('./scripts/webpack.conf');
 
 const paths = {
-  cache: 'src/cache.js',
   manifest: 'src/manifest.json',
-  templates: [
-    'src/**/*.html',
-    '!src/*/index.html',
-  ],
-  jsCollect: [
-    'src/**/*.js',
-    '!src/public/**',
-    '!src/injected.js',
+  copy: [
+    'src/public/**',
   ],
-  jsCommon: 'src/common.js',
-  jsBg: 'src/background/**/*.js',
-  jsOptions: 'src/options/**/*.js',
-  jsPopup: 'src/popup/**/*.js',
   locales: [
-    'src/**/*.js',
-    'src/**/*.html',
-    'src/**/*.json',
-    'src/**/*.yml',
+    'src/_locales/**',
   ],
-  copy: [
-    'src/injected.js',
-    'src/public/**',
-    'src/*/*.html',
-    'src/*/*.css',
+  templates: [
+    'src/**/*.@(js|html|json|yml|vue)',
   ],
 };
 
-gulp.task('clean', () => del(['dist']));
-
-gulp.task('watch', ['build'], () => {
-  gulp.watch([].concat(paths.cache, paths.templates), ['templates']);
-  gulp.watch(paths.jsCollect, ['js']);
-  gulp.watch(paths.copy, ['copy-files']);
-  gulp.watch(paths.locales, ['copy-i18n']);
-});
-
-gulp.task('lint', () => (
-  gulp.src([
-    'src/**/*.js',
-    '!src/public/**',
-  ])
-  .pipe(eslint())
-  .pipe(eslint.format())
-));
-
-var cacheObj;
-var collect;
+function webpackCallback(err, stats) {
+  if (err) {
+    gutil.log('[ERROR]', err);
+    return;
+  }
+  stats.stats.forEach(stat => {
+    const timeCost = (stat.endTime - stat.startTime) / 1000;
+    const chunks = Object.keys(stat.compilation.namedChunks).join(' ');
+    gutil.log(`Webpack built: [${timeCost.toFixed(3)}s] ${chunks}`);
+  });
+}
 
-gulp.task('collect-js', () => {
-  collect = definePack();
-  return gulp.src(paths.jsCollect)
-  .pipe(collect);
-});
-
-gulp.task('templates', ['collect-js'], () => {
-  cacheObj = templateCache('cache');
-  var stream = merge2([
-    gulp.src(paths.cache),
-    gulp.src(paths.templates).pipe(cacheObj),
-  ])
-  .pipe(concat('cache.js'))
-  .pipe(collect.pack({
-    getPath(file) {
-      return 'src/cache.js';
-    },
-  }));
-  if (isProd) stream = stream.pipe(uglify());
-  return stream.pipe(gulp.dest('dist'));
-});
+gulp.task('clean', () => del(['dist']));
 
-gulp.task('js-common', ['collect-js'], () => {
-  var stream = gulp.src(paths.jsCommon)
-  .pipe(collect.pack());
-  if (isProd) stream = stream.pipe(uglify());
-  return stream.pipe(gulp.dest('dist'));
-});
+gulp.task('pack', ['manifest', 'copy-files', 'copy-i18n']);
 
-gulp.task('js-bg', ['collect-js'], () => {
-  var stream = gulp.src(paths.jsBg)
-  .pipe(collect.pack({main: 'src/background/app.js'}))
-  .pipe(concat('background/app.js'));
-  if (isProd) stream = stream.pipe(uglify());
-  return stream.pipe(gulp.dest('dist'));
-});
-
-gulp.task('js-options', ['templates', 'collect-js'], () => {
-  var stream = gulp.src(paths.jsOptions)
-  .pipe(cacheObj.replace())
-  .pipe(collect.pack({main: 'src/options/app.js'}))
-  .pipe(concat('options/app.js'));
-  if (isProd) stream = stream.pipe(uglify());
-  return stream.pipe(gulp.dest('dist'));
+gulp.task('watch', ['pack', 'js-dev'], () => {
+  gulp.watch(paths.manifest, ['manifest']);
+  gulp.watch(paths.copy, ['copy-files']);
+  gulp.watch(paths.locales.concat(paths.templates), ['copy-i18n']);
 });
 
-gulp.task('js-popup', ['templates', 'collect-js'], () => {
-  var stream = gulp.src(paths.jsPopup)
-  .pipe(cacheObj.replace())
-  .pipe(collect.pack({main: 'src/popup/app.js'}))
-  .pipe(concat('popup/app.js'));
-  if (isProd) stream = stream.pipe(uglify());
-  return stream.pipe(gulp.dest('dist'))
-});
+gulp.task('build', ['pack', 'js-prd']);
 
-gulp.task('js', [
-  'js-common',
-  'js-bg',
-  'js-options',
-  'js-popup',
-]);
+gulp.task('js-dev', () => webpack(webpackConfig).watch({}, webpackCallback));
+gulp.task('js-prd', () => webpack(webpackConfig, webpackCallback));
 
 gulp.task('manifest', () => (
   gulp.src(paths.manifest, {base: 'src'})
@@ -138,16 +64,9 @@ gulp.task('manifest', () => (
 ));
 
 gulp.task('copy-files', () => {
-  const injectedFilter = gulpFilter(['**/injected.js'], {restore: true});
   const jsFilter = gulpFilter(['**/*.js'], {restore: true});
   const cssFilter = gulpFilter(['**/*.css'], {restore: true});
-  var stream = gulp.src(paths.copy, {base: 'src'})
-  .pipe(injectedFilter)
-  .pipe(wrap({
-    header: '!function(){\n',
-    footer: '\n}();',
-  }))
-  .pipe(injectedFilter.restore);
+  let stream = gulp.src(paths.copy, {base: 'src'});
   if (isProd) stream = stream
   .pipe(jsFilter)
   .pipe(uglify())
@@ -156,14 +75,16 @@ gulp.task('copy-files', () => {
   .pipe(cssFilter)
   .pipe(postcss([
     require('precss')(),
-    isProd && require('cssnano')({zindex: false}),
+    isProd && require('cssnano')({
+      // zindex: false,
+    }),
   ].filter(Boolean)))
   .pipe(cssFilter.restore)
   .pipe(gulp.dest('dist/'));
 });
 
 gulp.task('copy-i18n', () => (
-  gulp.src(paths.locales)
+  gulp.src(paths.templates)
   .pipe(i18n.extract({
     base: 'src',
     prefix: '_locales',
@@ -188,16 +109,8 @@ gulp.task('svg', () => (
   .pipe(gulp.dest('dist/public'))
 ));
 
-gulp.task('build', [
-  'js',
-  'manifest',
-  'copy-files',
-  'copy-i18n',
-  'svg',
-]);
-
 gulp.task('i18n', () => (
-  gulp.src(paths.locales)
+  gulp.src(paths.templates)
   .pipe(i18n.extract({
     base: 'src',
     prefix: '_locales',
@@ -208,5 +121,3 @@ gulp.task('i18n', () => (
   }))
   .pipe(gulp.dest('src'))
 ));
-
-gulp.task('default', ['build']);

+ 3 - 2
package.json

@@ -2,11 +2,12 @@
   "name": "violentmonkey",
   "version": "2.5.9",
   "scripts": {
-    "build": "webpack --config scripts/webpack.conf.js",
+    "dev": "gulp watch",
+    "build": "gulp build",
     "analyze": "webpack --profile --json --config scripts/webpack.conf.js | webpack-bundle-size-analyzer",
     "analyze:json": "webpack --profile --json --config scripts/webpack.conf.js > stats.json",
     "i18n": "gulp i18n",
-    "lint": "gulp lint",
+    "lint": "eslint src",
     "update": "node scripts/update",
     "svgo": "svgo icons",
     "test": "mocha"

+ 11 - 10
scripts/i18n.js

@@ -138,9 +138,14 @@ Locales.prototype.touch = function (key) {
 function extract(options) {
   const keys = new Set();
   const patterns = {
-    js: ['_\\.i18n\\(\'(\\w+)\'', 1],
+    default: ['\\bi18n\\(\'(\\w+)\'', 1],
     json: ['__MSG_(\\w+)__', 1],
-    html: ['i18n\\(\'(\\w+)\'\\)', 1],
+  };
+  const types = {
+    '.js': 'default',
+    '.json': 'json',
+    '.html': 'default',
+    '.vue': 'default',
   };
 
   const locales = new Locales(options.prefix, options.base);
@@ -161,14 +166,10 @@ function extract(options) {
 
   function bufferContents(file, enc, cb) {
     if (file.isNull()) return cb();
-    if (file.isStream())
-      return this.emit('error', new gutil.PluginError('VM-i18n', 'Stream is not supported.'));
-    if (file.path.endsWith('.js'))
-      extract(file.contents, 'js');
-    else if (file.path.endsWith('.json'))
-      extract(file.contents, 'json');
-    else if (file.path.endsWith('.html'))
-      extract(file.contents, ['html', 'js']);
+    if (file.isStream()) return this.emit('error', new gutil.PluginError('VM-i18n', 'Stream is not supported.'));
+    const extname = path.extname(file.path);
+    const type = types[extname];
+    type && extract(file.contents, type);
     cb();
   }
 

+ 0 - 59
scripts/templateCache.js

@@ -1,59 +0,0 @@
-const path = require('path');
-const gutil = require('gulp-util');
-const through = require('through2');
-const minify = require('html-minifier').minify;
-
-function replacePlugin(contents, objName) {
-  const re = new RegExp(`${objName}\\.get\\('(.*?)'\\)`, 'g');
-  return through.obj(function (file, enc, cb) {
-    const dirname = path.dirname(file.path);
-    file.contents = new Buffer(String(file.contents).replace(re, (m, name) => {
-      const filepath = path.resolve(dirname, name);
-      const item = contents[filepath];
-      if (!item) throw new Error(`\
-Cache not found: ${name}
-Required by:
-- ${file.path}`);
-      return `${objName}.get(${item.id})`;
-    }));
-    cb(null, file);
-  });
-}
-
-module.exports = function templateCache(objName) {
-  const contentTpl = `${objName}.put(<%= name %>, <%= content %>);\n`;
-  const header = `\n\n/* Templates cached with love :) */\n`;
-  const contents = {};
-
-  function bufferContents(file, enc, cb) {
-    if (file.isNull()) return cb();
-    if (file.isStream()) return this.emit('error', new gutil.PluginError('VM-cache', 'Stream is not supported.'));
-    contents[file.path] = {
-      content: minify(String(file.contents), {
-        removeComments: true,
-        collapseWhitespace: true,
-        conservativeCollapse: true,
-        removeAttributeQuotes: true,
-      }),
-    };
-    cb();
-  }
-
-  function endStream(cb) {
-    var keys = Object.keys(contents).sort();
-    keys.forEach((key, i) => contents[key].id = i + 1);
-    this.replace = () => replacePlugin(contents, objName);
-    const templates = keys.map(key => {
-      const item = contents[key];
-      return `${objName}.put(${item.id}, ${JSON.stringify(item.content)});`;
-    }).join('\n');
-    this.push(new gutil.File({
-      base: '',
-      path: 'template.js',
-      contents: new Buffer(header + templates),
-    }));
-    cb();
-  }
-
-  return through.obj(bufferContents, endStream);
-};

+ 1 - 1
scripts/webpack.conf.js

@@ -51,7 +51,7 @@ const base = {
     })),
   },
   // cheap-module-eval-source-map is faster for development
-  devtool: IS_DEV ? '#cheap-module-eval-source-map' : false,
+  devtool: IS_DEV ? '#inline-source-map' : false,
 };
 
 const targets = module.exports = [];

+ 0 - 14
scripts/wrap.js

@@ -1,14 +0,0 @@
-const gutil = require('gulp-util');
-const through = require('through2');
-
-module.exports = function (options) {
-  return through.obj(function (file, enc, cb) {
-    if (file.isNull()) return cb();
-    if (file.isStream()) return this.emit('error', new gutil.PluginError('VM-wrap', 'Stream is not supported.'));
-    const header = options.header || '';
-    const contents = String(file.contents);
-    const footer = options.footer || '';
-    file.contents = new Buffer(header + contents + footer);
-    cb(null, file);
-  });
-};

+ 2 - 2
src/background/index.html

@@ -1,9 +1,9 @@
-<!DOCTYPE html>
+<!DOCTYPE html>
 <html>
 <head>
 <meta charset="utf-8">
 <title>ViolentMonkey</title>
-<script src="/public/mylib/browser.js"></script>
+<script src="/public/browser.js"></script>
 </head>
 <body></body>
 </html>

+ 16 - 7
src/background/sync/base.js

@@ -123,9 +123,7 @@ export const BaseService = serviceFactory({
   urlPrefix: '',
   metaFile: 'Violentmonkey',
   delay(time) {
-    return new Promise(resolve => {
-      setTimeout(resolve, time == null ? this.delayTime : time);
-    });
+    return new Promise(resolve => { setTimeout(resolve, time); });
   },
   initialize(name) {
     this.onStateChange = debounce(this.onStateChange.bind(this));
@@ -237,12 +235,23 @@ export const BaseService = serviceFactory({
   request(options) {
     const { progress } = this;
     let lastFetch;
-    if (options.noDelay) {
-      lastFetch = Promise.resolve();
+    if (options.delay == null) {
+      lastFetch = Promise.resolve(Date.now());
     } else {
-      lastFetch = this.lastFetch;
-      this.lastFetch = lastFetch.then(() => this.delay());
+      lastFetch = this.lastFetch
+      .then(ts => new Promise(resolve => {
+        let delay = options.delay;
+        if (!isNaN(delay)) delay = this.delayTime;
+        const delta = delay - (Date.now() - ts);
+        if (delta > 0) {
+          setTimeout(resolve, delta);
+        } else {
+          resolve();
+        }
+      }))
+      .then(() => Date.now());
     }
+    this.lastFetch = lastFetch;
     progress.total += 1;
     this.onStateChange();
     return lastFetch.then(() => new Promise((resolve, reject) => {

+ 3 - 8
src/background/sync/onedrive.js

@@ -73,14 +73,9 @@ const OneDrive = BaseService.extend({
       url: `/drive/special/approot:/${encodeURIComponent(path)}`,
       responseType: 'json',
     })
-    .then(data => new Promise((resolve, reject) => {
-      const url = data['@content.downloadUrl'];
-      const xhr = new XMLHttpRequest();
-      xhr.open('GET', url, true);
-      xhr.onload = () => { resolve(xhr.responseText); };
-      xhr.onerror = () => { reject(); };
-      xhr.ontimeout = () => { reject(); };
-      xhr.send();
+    .then(data => this.request({
+      url: data['@content.downloadUrl'],
+      delay: 0,
     }));
   },
   put(path, data) {

+ 1 - 1
src/manifest.json

@@ -26,7 +26,7 @@
   "content_scripts": [
     {
       "js": [
-        "public/mylib/browser.js",
+        "public/browser.js",
         "injected.js"
       ],
       "matches": [

+ 2 - 0
src/options/app.js

@@ -6,6 +6,8 @@ import Main from './views/main';
 import Confirm from './views/confirm';
 import './style.css';
 
+Vue.prototype.i18n = i18n;
+
 Object.assign(store, {
   loading: false,
   cache: {},

+ 4 - 1
src/popup/app.js

@@ -1,8 +1,11 @@
 import Vue from 'vue';
 import options from 'src/common/options';
-import { sendMessage } from 'src/common';
+import { i18n, sendMessage } from 'src/common';
 import App from './views/app';
 import { store } from './utils';
+import './style.css';
+
+Vue.prototype.i18n = i18n;
 
 new Vue({
   render: h => h(App),

+ 1 - 2
src/popup/index.html

@@ -3,8 +3,7 @@
 <head>
 <meta charset="utf-8">
 <title>Popup Menu - Violentmonkey</title>
-<link rel="stylesheet" href="style.css">
-<script src="/public/mylib/browser.js"></script>
+<script src="/public/browser.js"></script>
 </head>
 <body>
 <div id="app"></div>

+ 7 - 7
src/popup/style.css

@@ -1,10 +1,10 @@
-* {
-  margin: 0;
-  padding: 0;
-  box-sizing: border-box;
-}
-html {
-  font: 14px menu;
+* {
+  margin: 0;
+  padding: 0;
+  box-sizing: border-box;
+}
+html {
+  font: 14px menu;
 }
 body {
   min-width: 20em;