From b04c293826080757a21e2aa2977bf68e07536563 Mon Sep 17 00:00:00 2001 From: "xuanji.jw" Date: Mon, 11 Jul 2016 17:28:25 +0800 Subject: [PATCH] enhance inject weinre --- .eslintignore | 2 -- .eslintrc | 3 ++- package.json | 5 +++-- src/index.js | 47 +++++++++++++++++++++++++++++---------------- src/injectScript.js | 33 +++++++++++++++++++++++++++++++ src/util.js | 21 ++++++++++++++++++++ test/index-test.js | 16 +++++++-------- 7 files changed, 97 insertions(+), 30 deletions(-) delete mode 100644 .eslintignore create mode 100644 src/injectScript.js create mode 100644 src/util.js diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index cc821ad..0000000 --- a/.eslintignore +++ /dev/null @@ -1,2 +0,0 @@ -**/*/__tests__ -**/*/__fixtures__ diff --git a/.eslintrc b/.eslintrc index b4c2f5f..a514c59 100644 --- a/.eslintrc +++ b/.eslintrc @@ -2,7 +2,8 @@ "parser": "babel-eslint", "extends": "eslint-config-airbnb/base", "rules": { - "no-console": [0] + "no-console": [0], + "no-param-reassign": [0] }, "ecmaFeatures": { "generators": 1, diff --git a/package.json b/package.json index 8e90afa..b10679b 100644 --- a/package.json +++ b/package.json @@ -18,10 +18,11 @@ "dependencies": { "coffee-script": "^1.10.0", "internal-ip": "^1.2.0", + "webpack-core": "^0.6.8", "weinre": "^2.0.0-pre-I0Z7U9OV" }, "devDependencies": { - "atool-build": "0.7.x", + "atool-build": "0.7.x", "babel-cli": "^6.10.1", "babel-core": "^6.10.4", "babel-eslint": "^6.1.0", @@ -52,4 +53,4 @@ "package.json", "README.md" ] -} +} \ No newline at end of file diff --git a/src/index.js b/src/index.js index 4b45e60..8866b89 100644 --- a/src/index.js +++ b/src/index.js @@ -2,6 +2,9 @@ import { existsSync, readFileSync } from 'fs'; import { parse } from 'url'; import { join } from 'path'; +import { getInjectWeinreContent } from './util'; +import InjectScript from './injectScript'; + const localIP = require('internal-ip')(); /** @@ -13,7 +16,7 @@ import { run } from 'weinre'; let defaultOpts = { httpPort: 8990, - boundHost: 'localhost', + boundHost: localIP, verbose: false, debug: false, readTimeout: 5, @@ -22,33 +25,30 @@ let defaultOpts = { }; export default { - 'middleware.before'() { - const { log, query } = this; - defaultOpts.boundHost = localIP; - defaultOpts = { ...defaultOpts, ...query }; + name: 'dora-plugin-weinre', + 'middleware.before'() { + const { log } = this; run(defaultOpts); log.info(`weinre is started, servering at http://${defaultOpts.boundHost}:${defaultOpts.httpPort}`); }, 'middleware'() { - const { cwd } = this; + const { cwd, get } = this; + const compiler = get('compiler'); + if (!compiler) { + throw new Error('[error] must used together with dora-plugin-webpack'); + } return function* middleFunc(next) { - const fileName = parse(this.url).pathname; + const pathName = parse(this.url).pathname; + const fileName = pathName === '/' ? 'index.html' : pathName; const filePath = join(cwd, fileName); - const isHTML = /\.html?$/.test(this.url.split('?')[0]); + const isHTML = /\.html?$/.test(fileName); if (isHTML && existsSync(filePath)) { - const injectScript = ``; + const injectContent = getInjectWeinreContent(defaultOpts.boundHost, defaultOpts.httpPort); + const injectScript = ``; let content = readFileSync(filePath, 'utf-8'); - const docTypeReg = new RegExp('^\s*\<\!DOCTYPE\s*.+\>.*$', 'im'); - const docType = content.match(docTypeReg); - if (docType) { - content = content.replace(docTypeReg, docType[0] + injectScript); - this.body = content; - - return; - } content = injectScript + content; this.body = content; @@ -57,4 +57,17 @@ export default { yield next; }; }, + + 'webpack.updateConfig.finally'(webpackConfig) { + const { query } = this; + + defaultOpts = { ...defaultOpts, ...query }; + + webpackConfig.plugins.push(new InjectScript({ + boundHost: defaultOpts.boundHost, + httpPort: defaultOpts.httpPort, + })); + + return webpackConfig; + }, }; diff --git a/src/injectScript.js b/src/injectScript.js new file mode 100644 index 0000000..bb75225 --- /dev/null +++ b/src/injectScript.js @@ -0,0 +1,33 @@ +import ConcatSource from 'webpack-core/lib/ConcatSource'; +import { getInjectWeinreContent } from './util'; + +export default class InjectScript { + static defaults = { + httpPort: 8990, + boundHost: 'localhost', + }; + + constructor(options) { + this.options = { ...InjectScript.defaults, ...options }; + } + + apply(compiler) { + compiler.plugin('compilation', compilation => { + const opts = this.options; + compilation.plugin('optimize-chunk-assets', (chunks, callback) => { + chunks.forEach(chunk => { + chunk.files.filter(file => /.(js)$/.test(file)).forEach(file => { + const injectContent = getInjectWeinreContent(opts.injectHost, opts.port); + compilation.assets[file] = new ConcatSource( + injectContent, + '\n', + compilation.assets[file] + ); + }); + }); + + callback(); + }); + }); + } +} diff --git a/src/util.js b/src/util.js new file mode 100644 index 0000000..8dde441 --- /dev/null +++ b/src/util.js @@ -0,0 +1,21 @@ +export function getInjectWeinreContent(host, port) { + const src = `http://${host}:${port}/target/target-script-min.js#anonymous`; + const injectContent = [ + '// weinre', + '(function() {', + ' if (typeof window === "undefined") { return };', + ' window.onload = function() {', + ' var id = "webpack-weinre-plugin-script";', + ' if (document.getElementById(id)) { return; }', + ' var el = document.createElement("script");', + ' el.id = id;', + ' el.async = true;', + ` el.src = "${src}";`, + ' document.body.appendChild(el);', + ' }', + '}());', + '', + ].join('\n'); + + return injectContent; +} diff --git a/test/index-test.js b/test/index-test.js index 281142c..0ed77a7 100644 --- a/test/index-test.js +++ b/test/index-test.js @@ -3,16 +3,16 @@ import { join } from 'path'; import request from 'supertest'; const localIP = require('internal-ip')(); -const port = '12345'; +const port = '1234'; describe('index', () => { - describe('livereload.js', () => { + describe('weinre', () => { const cwd = process.cwd(); before(done => { process.chdir(join(__dirname, './fixtures/normal')); dora({ port, - plugins: ['../../../src/index?{httpPort:8888}'], + plugins: ['dora-plugin-webpack', '../../../src/index?{httpPort:8888}'], cwd: join(__dirname, './fixtures/normal'), }, done); }); @@ -43,7 +43,7 @@ describe('index', () => { .expect(200) .end((err, res) => { if (err) return done(err); - if (res.text.indexOf(``) < 0) { + if (res.text.indexOf('// weinre') < 0) { const e = new Error('/target/target-script-min.js#anonymous is not injected'); return done(e); @@ -59,7 +59,7 @@ describe('index', () => { .expect(200) .end((err, res) => { if (err) return done(err); - if (res.text.indexOf(``) < 0) { + if (res.text.indexOf('// weinre') < 0) { const e = new Error('/target/target-script-min.js#anonymous is not injected'); return done(e); @@ -69,14 +69,14 @@ describe('index', () => { }); }); - it('GET /index.js should not be handled', done => { + it('GET /index.js should be handled', done => { request(`http://localhost:${port}`) .get('/index.js') .expect(200) .end((err, res) => { if (err) return done(err); - if (res.text.indexOf('console.log(1);') < 0) { - const e = new Error('other types of files should not be handled'); + if (res.text.indexOf('// weinre') < 0) { + const e = new Error('other types of files should be handled'); return done(e); }