Skip to content
This repository has been archived by the owner on Mar 10, 2020. It is now read-only.

Commit

Permalink
refactor: Switch to webpack and wreck
Browse files Browse the repository at this point in the history
This moves from browserify to webpack and from request to wreck.
The resulting browser bundler is about half the size.
  • Loading branch information
dignifiedquire committed Nov 18, 2015
1 parent 7589234 commit c2a6ad3
Show file tree
Hide file tree
Showing 7 changed files with 176 additions and 149 deletions.
26 changes: 15 additions & 11 deletions karma.conf.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
var webpackConfig = require('./tasks/config').webpack

module.exports = function (config) {
if (!process.env.DEBUG) {
var reporters = ['progress']

if (process.env.TRAVIS) {
if (!process.env.SAUCE_USERNAME || !process.env.SAUCE_ACCESS_KEY) {
console.log('Make sure the SAUCE_USERNAME and SAUCE_ACCESS_KEY environment variables are set.')
process.exit(1)
}

reporters.push('saucelabs')
}

// Browsers to run on Sauce Labs
Expand Down Expand Up @@ -39,21 +45,19 @@ module.exports = function (config) {

config.set({
basePath: '',
frameworks: ['browserify', 'mocha'],
frameworks: ['mocha'],
files: [
'test/tests.js'
],
exclude: [],
preprocessors: {
'test/**/*.js': ['browserify']
'test/**/*.js': ['webpack']
},

browserify: {
debug: true,
transform: [
'brfs',
['babelify', {presets: ['es2015']}]
]
webpack: webpackConfig.dev,

webpackMiddleware: {
noInfo: true
},

sauceLabs: {
Expand All @@ -65,13 +69,13 @@ module.exports = function (config) {
}
},

reporters: ['progress', 'saucelabs'],
reporters: reporters,
port: 9876,
colors: true,
logLevel: process.env.DEBUG ? config.LOG_DEBUG : config.LOG_INFO,
autoWatch: false,
customLaunchers: customLaunchers,
browsers: process.env.DEBUG ? ['Chrome'] : Object.keys(customLaunchers),
browsers: process.env.TRAVIS ? Object.keys(customLaunchers) : ['Chrome'],
singleRun: false,
concurrency: 2,
browserNoActivityTimeout: 600000
Expand Down
27 changes: 12 additions & 15 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,14 @@
"description": "A client library for the IPFS API",
"main": "src/index.js",
"dependencies": {
"brfs": "^1.4.0",
"merge-stream": "^1.0.0",
"multiaddr": "^1.0.0",
"multipart-stream": "^2.0.0",
"request": "^2.65.0",
"qs": "^6.0.0",
"vinyl": "^1.1.0",
"vinyl-fs-browser": "^2.1.1-1",
"vinyl-multipart-stream": "^1.2.6"
},
"browserify": {
"transform": [
"brfs"
]
"vinyl-multipart-stream": "^1.2.6",
"wreck": "^7.0.0"
},
"engines": {
"node": "^4.0.0"
Expand All @@ -26,10 +21,11 @@
"url": "https://github.com/ipfs/js-ipfs-api"
},
"devDependencies": {
"babel-core": "^6.1.21",
"babel-eslint": "^4.1.3",
"babel-loader": "^6.2.0",
"babel-plugin-transform-runtime": "^6.1.18",
"babel-preset-es2015": "^6.0.15",
"babelify": "^7.2.0",
"browserify": "^12.0.1",
"concurrently": "^1.0.0",
"eslint-config-standard": "^4.4.0",
"eslint-plugin-standard": "^1.3.1",
Expand All @@ -38,26 +34,27 @@
"gulp-load-plugins": "^1.0.0",
"gulp-mocha": "^2.1.3",
"gulp-size": "^2.0.0",
"gulp-sourcemaps": "^1.6.0",
"gulp-uglify": "^1.5.1",
"gulp-util": "^3.0.7",
"https-browserify": "0.0.1",
"ipfsd-ctl": "^0.6.1",
"json-loader": "^0.5.3",
"karma": "^0.13.11",
"karma-browserify": "^4.4.0",
"karma-chrome-launcher": "^0.2.1",
"karma-mocha": "^0.2.0",
"karma-sauce-launcher": "^0.3.0",
"karma-webpack": "^1.7.0",
"mocha": "^2.3.3",
"pre-commit": "^1.0.6",
"raw-loader": "^0.5.1",
"require-dir": "^0.3.0",
"rimraf": "^2.4.3",
"run-sequence": "^1.1.4",
"uglify-js": "^2.4.24",
"vinyl-buffer": "^1.0.0",
"vinyl-source-stream": "^1.1.0"
"vinyl-source-stream": "^1.1.0",
"webpack-stream": "^2.1.1"
},
"scripts": {
"testD": "DEBUG=true gulp test:browser",
"test": "gulp test",
"test:node": "gulp test:node",
"test:browser": "gulp test:browser",
Expand Down
13 changes: 8 additions & 5 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
var multiaddr = require('multiaddr')
var getConfig = require('./config')
var getRequestAPI = require('./request-api')
var request = require('request')
var Wreck = require('wreck')

exports = module.exports = IpfsAPI

Expand Down Expand Up @@ -65,13 +65,16 @@ function IpfsAPI (host_or_multiaddr, port) {
}

if (typeof files === 'string' && files.startsWith('http')) {
files = request.get({
url: files,
withCredentials: false
Wreck.request('GET', files, null, (err, res) => {
if (err) return cb(err)

requestAPI('add', null, opts, res, cb)
})

return
}

return requestAPI('add', null, opts, files, cb)
requestAPI('add', null, opts, files, cb)
}

self.cat = argCommand('cat')
Expand Down
124 changes: 45 additions & 79 deletions src/request-api.js
Original file line number Diff line number Diff line change
@@ -1,95 +1,57 @@
'use strict'

const request = require('request')
const Wreck = require('wreck')
const Qs = require('qs')
const getFilesStream = require('./get-files-stream')
const stream = require('stream')

const isNode = !global.window

// -- Internal

function onEnd (buffer, result, passThrough, cb) {
return (err, res, body) => {
function onEnd (buffer, cb) {
return (err, res) => {
if (err) {
return cb(err)
}

if (res.statusCode >= 400 || !res.statusCode) {
var error = new Error(`Server responded with ${res.statuscode}: ${body}`)
try {
body = JSON.parse(body)
error.code = body.Code
error.message = body.Message
} catch (e) {
error.body = body
}
return cb(error)
}
const stream = !!res.headers['x-stream-output']
const chunkedObjects = !!res.headers['x-chunked-output']

if (result.stream) {
cb(null, passThrough)
passThrough.resume()
passThrough.end()
return
}

if ((result.stream && !buffer) ||
(result.chunkedObjects && buffer)) {
return cb(null, body)
}

if (result.chunkedObjects) return cb(null, result.objects)

let parsedBody
try {
parsedBody = JSON.parse(body)
} catch (e) {
parsedBody = body
if (res.statusCode >= 400 || !res.statusCode) {
var error = new Error(`Server responded with ${res.statusCode}`)

Wreck.read(res, {json: true}, (err, payload) => {
if (err) {
error.code = payload.Code
error.message = payload.Message
}
cb(error)
})
}

cb(null, parsedBody)
}
}
if (stream && !buffer) return cb(null, res)

function onData (result, passThrough) {
return chunk => {
if (result.stream) {
passThrough.write(chunk)
if (chunkedObjects) {
const parsed = []
res.on('data', chunk => parsed.push(JSON.parse(chunk)))
res.on('end', () => cb(null, parsed))
return
}
if (!result.chunkedObjects) return

try {
const obj = JSON.parse(chunk.toString())
result.objects.push(obj)
} catch (e) {
result.chunkedObjects = false
}
}
}
Wreck.read(res, null, (err, payload) => {
if (err) return cb(err)

function onResponse (result) {
return res => {
result.stream = !!res.headers['x-stream-output']
result.chunkedObjects = !!res.headers['x-chunked-output']
}
}
let parsed

function makeRequest (opts, buffer, cb) {
// this option is only used internally, not passed to daemon
delete opts.qs.followSymlinks
try {
parsed = JSON.parse(payload.toString())
} catch (err2) {
parsed = payload.toString()
}

const result = {
stream: false,
chunkedObjects: false,
objects: []
cb(null, parsed)
})
}

var passThrough = new stream.PassThrough()

return request(opts, onEnd(buffer, result, passThrough, cb))
.on('data', onData(result, passThrough))
.on('response', onResponse(result))
}

function requestAPI (config, path, args, qs, files, buffer, cb) {
Expand All @@ -115,14 +77,18 @@ function requestAPI (config, path, args, qs, files, buffer, cb) {

qs['stream-channels'] = true

let stream
if (files) {
stream = getFilesStream(files, qs)
}

// this option is only used internally, not passed to daemon
delete qs.followSymlinks

const opts = {
method: files ? 'POST' : 'GET',
uri: `http://${config.host}:${config.port}${config['api-path']}${path}`,
qs: qs,
useQuerystring: true,
headers: {},
withCredentials: false,
gzip: true
uri: `http://${config.host}:${config.port}${config['api-path']}${path}?${Qs.stringify(qs, {arrayFormat: 'repeat'})}`,
headers: {}
}

if (isNode) {
Expand All @@ -131,16 +97,16 @@ function requestAPI (config, path, args, qs, files, buffer, cb) {
}

if (files) {
const stream = getFilesStream(files, qs)
if (!stream.boundary) {
return cb(new Error('No boundary in multipart stream'))
}

opts.headers['Content-Type'] = `multipart/form-data; boundary=${stream.boundary}`
stream.pipe(makeRequest(opts, buffer, cb))
} else {
makeRequest(opts, buffer, cb)
opts.downstreamRes = stream
opts.payload = stream
}

Wreck.request(opts.method, opts.uri, opts, onEnd(buffer, cb))
}

// -- Interface
Expand Down
45 changes: 15 additions & 30 deletions tasks/build.js
Original file line number Diff line number Diff line change
@@ -1,44 +1,29 @@
var browserify = require('browserify')
var gulp = require('gulp')
var source = require('vinyl-source-stream')
var buffer = require('vinyl-buffer')
var runSequence = require('run-sequence')
var rimraf = require('rimraf')
var $ = require('gulp-load-plugins')()
const gulp = require('gulp')
const $ = require('gulp-load-plugins')()
const webpack = require('webpack-stream')
const rimraf = require('rimraf')
const runSequence = require('run-sequence')

function getBrowserify () {
return browserify({
entries: ['./src/index.js'],
debug: true,
standalone: 'ipfsAPI'
})
.transform('brfs')
.transform('babelify', {presets: ['es2015']})
}
const config = require('./config')

gulp.task('clean', function (done) {
rimraf('./dist', done)
})

gulp.task('build:nonminified', function () {
return getBrowserify().bundle()
.pipe(source('./ipfsapi.js'))
.pipe(buffer())
return gulp.src('src/index.js')
.pipe(webpack(config.webpack.dev))
.pipe($.size())
.pipe(gulp.dest('./dist/'))
.pipe(gulp.dest('dist/'))
})

gulp.task('build:minified', function () {
return getBrowserify().bundle()
.pipe(source('./ipfsapi.min.js'))
.pipe(buffer())
.pipe($.sourcemaps.init({loadMaps: true}))
// Add transformation tasks to the pipeline here.
.pipe($.uglify())
.on('error', $.util.log)
.pipe($.sourcemaps.write('./'))
.pipe($.size({showFiles: true}))
.pipe(gulp.dest('./dist/'))
config.webpack.prod.output.filename = 'ipfsapi.min.js'

return gulp.src('src/index.js')
.pipe(webpack(config.webpack.prod))
.pipe($.size())
.pipe(gulp.dest('dist/'))
})

gulp.task('build', ['clean'], function (done) {
Expand Down
Loading

0 comments on commit c2a6ad3

Please sign in to comment.