Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

--slim by default. Fixes gh-412, Fixes gh-418 #420

Merged
merged 1 commit into from
Oct 30, 2015

Conversation

rwaldron
Copy link
Contributor

No description provided.

// If there is only one file in this project, then there is
// no reason to use the code generated by browserify, because
// it will always have the module loading boilerplate included.
if (opts.single || fileCount === 1) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice catch. :)

@HipsterBrown
Copy link
Contributor

Great fixes and refactor. 👍

@rwaldron
Copy link
Contributor Author

@HipsterBrown thanks for the review :D

})
.option('slimPath', {
default: 'build.js'
})
.option('full', {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I missed this before. Should this option, and making --slim the default action, be added to the push command as well?

.option('full', {
flag: true,
default: false,
help: 'Bundle all files in project'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We may want to make this more explicit: "Bundle all files in project including those not used by the program".

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Bundle all files in project including those not used by the program, but excluding any files matched by non-negated rules in .tesselignore"

@HipsterBrown
Copy link
Contributor

From @LinusU in another issue:

Preferably don't touch the filesystem at all, aka. get a stream from browserify and pipe that straight to tar.pack. If that isn't possible (I think it is thought), let the temporary file live in the OS temporary directory, using e.g. fs-temp.

Thoughts on this approach @rwaldron?

@rwaldron
Copy link
Contributor Author

@HipsterBrown that's out of scope for this changeset. I don't want to pig-pile a bunch of changes into one PR.

@HipsterBrown
Copy link
Contributor

@rwaldron That works for me. What about having a better namespaced path for the generated bundle?

@rwaldron
Copy link
Contributor Author

path for the generated bundle?

Yeah, that should be addressed here, update to follow

@rwaldron
Copy link
Contributor Author

@HipsterBrown

that's out of scope for this changeset. I don't want to pig-pile a bunch of changes into one PR.

After re-reviewing the conversation, I decided that you and @LinusU were right and this needed to be addressed.

The slim path now...

  • bundles with browserify (as before)
  • optimizes if one file
  • creates an "in-memory" directory using @LinusU's fs-temp
  • writes the bundle to that temp dir
  • tars the temp dir and resolves with the buffer (as before)
  • cleans up the temp dir

No there is no chance of paving over user project files! Thanks for highlighting this issue :)

@rwaldron rwaldron force-pushed the slim-by-default branch 2 times, most recently from 4ab7d60 to e23853d Compare October 30, 2015 17:30
@LinusU
Copy link
Contributor

LinusU commented Oct 30, 2015

Just to clarify about fs-temp, it doesn't create the directory in-memory, it will reside in the os temporary directory (e.g. /tmp).

I think that this is the minimum we should do thought, I'm pro this change.

However, what I really wanted was something like this:

const source = browserify(...).bundle()
const gzip = zlib.createGzipStream()

source.pipe(gzip).pipe(/* to the tessel */)

It's unnecessary to use tar since we are only sending one file over. I also feel it's a bit overkill to create a temporary directory, stream the entire file to disk, use a new stream that iterates directories, then create a tar stream out of that and then pipe that to the tessel. In reality, the only thing that happens is that a few bytes gets prepended to the stream before the file. tar is a very simple format.

But as I said, this is absolutely good for now!

@rwaldron
Copy link
Contributor Author

Just to clarify about fs-temp, it doesn't create the directory in-memory, it will reside in the os temporary directory (e.g. /tmp).

Yep, I was monitoring the actual creation of dirs—easier to think about an ephemeral concept as "in-memory"

const source = browserify(...).bundle()
const gzip = zlib.createGzipStream()
source.pipe(gzip).pipe(/* to the tessel */)

It's unnecessary to use tar since we are only sending one file over.

This was brought up in another thread and I held off responding because I thought @HipsterBrown's mention of the --full path was sufficient—I based the changes in this patch on your response to that. If we went this route, it would require having a different remote process command to handle extracting the gzip contents, with potentially different outcomes that would have to be handled. The approach here works exactly as it should for both a directory with a single file and a directory with arbitrary number of files and subdirectories (as in the --full flag case). In both cases the result is either resolving with the bundle buffer, or rejecting with some error, and then displaying some useful information.

I also feel it's a bit overkill to create a temporary directory, stream the entire file to disk, use a new stream that iterates directories, then create a tar stream out of that and then pipe that to the tessel.

Skipping the phase where this occurs means eliminating the opportunity to optimize the resulting bundle; in cases where browserify has only bundled a single file, the original file (minified) will always be a smaller payload because it will have the same contents as the browserify result, but will not have the module loading/dependency boilerplate. Also, the same argument I gave above applies to this phase.

Do you know of a way to simplify the operation that preserves the all of these semantics?

@rwaldron rwaldron force-pushed the slim-by-default branch 2 times, most recently from 5d89658 to d1c4a18 Compare October 30, 2015 19:36
@rwaldron
Copy link
Contributor Author

Thanks for the reviews!

rwaldron added a commit that referenced this pull request Oct 30, 2015
@rwaldron rwaldron merged commit 9d5eb3e into tessel:master Oct 30, 2015
@LinusU
Copy link
Contributor

LinusU commented Oct 31, 2015

I just realized that the tar header needs to contain the length of the file :(

I thought that I was so smart thinking there was a way to just append the header ourselves but that won't work. I can totally see the benefit of having the same receiving mechanism for both a single file and a directory of files.

A thing that I would like slightly more, mostly because it skips the Sync part of fs-temp, would be to stream it to a file and skip the directory. Than roll the tar files using tar-stream instead of tar. I need to check my sources on this but I remember tar-stream being significantly faster than tar as well. The downside to this is that we would bring in both tar and tar-stream which feels a bit redundant.

const fs = require('fs')
const tar = require('tar-stream')
const temp = require('fs-temp')
const browserify = require('browserify')

const file = temp.createWriteStream()
const source = browserify(...).bundle()

source.pipe(file).on('finish', function () {
  const pack = tar.pack()
  const infile = fs.createReadStream(file.path)

  const header = { name: 'index.js', size: file.bytesWritten }
  const entry = pack.entry(header, function (err) {
    if (err) throw err

    pack.finialize()
  })

  infile.pipe(entry)

  pack.pipe(/* To the Tessel */)
})

I don't know if this feels like extra work, but on the other hand, getting the deployment to go as fast as possible would be very nice. It would be interesting to see if actually yields any difference though. It feels cleaner since it doesn't use Sync methods and reduces the amount of "unnecessary" work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants