版本控制包文件

Versioning bundle file

我有一个问题,每次我修改我的代码js,我必须重新加载我的浏览器三四次以清除缓存。所以很痛苦。

我正在寻找一种解决方案,例如对 gulp 生成的 bundle.js 进行版本控制。每次修改我的代码时,我都需要创建一个包含随机数的捆绑文件,例如 bundle-1287138.js[=65= 中的脚本标签]需要自动更新

<script src = "/dist/bundle-1287138.js"></script>

我该怎么办?

下面的代码是我现在的gulpfile.js:

var gulp       = require('gulp');
var fs         = require("fs");
var browserify = require("browserify");
var babelify   = require("babelify");
var source     = require('vinyl-source-stream');
var gutil      = require('gulp-util');

gulp.task('es6', function() {
    browserify({ debug: true })
        .transform(babelify)
        .require("./main.js", { entry: true })
        .bundle()
        .on('error',gutil.log)
        .pipe(source('./dist/bundle.js'))
        .pipe(gulp.dest('./'));
});

gulp.task('watch',function() {
    gulp.watch(['app.jsx', 'main.js', './components/**/*.jsx'], ['es6'])
});

gulp.task('default', ['es6','watch']);

谢谢!

更新

正如 MadScone 所说,我使用 BrowserSync 并且效果很好。只有一个问题,保存后有延迟(8 - 9 秒)。

这是我的文件夹结构:

- api
- frontend
    - gulpfile.js
- index.js

index.js中,我使用BrowserSync:

var express     = require('express');
var app         = express();
var browserSync = require('browser-sync');

var bs          = browserSync({ logSnippet: false });
bs.watch("frontend/dist/bundle.js", function() {
    var curr = new Date();
    console.log("changed " + curr.getHours() + ":" + curr.getMinutes() + ":" + curr.getSeconds());
    bs.reload();
});

app.use(require('connect-browser-sync')(bs));
app.use('/', express.static(path.join(__dirname, 'frontend')));

var server = app.listen(3000, function () {
    console.log('Server running at http://127.0.0.1:3000/');
});

并且在 gulpfile.js 中,我正在使用 gulp 构建我的 bundle.js :

var gulp        = require('gulp');
var fs          = require("fs");
var browserify  = require("browserify");
var babelify    = require("babelify");
var source      = require('vinyl-source-stream');
var gutil       = require('gulp-util');

gulp.task('es6', function() {
    browserify({ debug: true })
        .transform(babelify)
        .require("./main.js", { entry: true })
        .bundle()
        .on('error',gutil.log)
        .pipe(source('./dist/bundle.js'))
        .pipe(gulp.dest('./'));
});

gulp.task('watch',function() {
    gulp.watch(['app.jsx', 'main.js', './components/**/*.jsx'], ['es6'])
});

gulp.task('default', ['es6', 'watch']);

当我修改并保存我的代码时,gulp es6 任务重新生成 bundle.js 并生成以下日志:

[23:49:54] Starting 'es6'...
[23:49:54] Finished 'es6' after 6 ms 

因为 bundle.js 文件已更改,所以 BrowserSync 会在 5 秒后开始工作...

changed 23:49:59
[BS] Reloading Browsers...

能否请您解释一下为什么它在 es6 任务后没有立即重新加载。

谢谢!

如果您想在每次捆绑更改时重新加载浏览器,您真的应该研究 Browsersync,这是一种更好的方法。但是,如果您出于某种原因不想使用 Browsersync,下面有一个解决方案。

您可以使用 node-randomstring to generate the file name (or there are lots of other ways to do that) and then use gulp-inject 之类的东西将捆绑包注入您的 HTML。

运行任务inject产生你想要的输出。

var gulp         = require('gulp');
var fs           = require('fs');
var browserify   = require('browserify');
var babelify     = require('babelify');
var source       = require('vinyl-source-stream');
var gutil        = require('gulp-util');
var path         = require('path');
var inject       = require('gulp-inject');
var del          = require('del');
var randomString = require('randomstring');

var BUILD_DIRECTORY = 'dist';

gulp.task('es6', function() {

    // Create random file name.
    var hash = randomString.generate(8);
    var name = path.join(BUILD_DIRECTORY, 'bundle-' + hash + '.js');

    return browserify({ debug: true })
        .transform(babelify)
        .require('./main.js', { entry: true })
        .bundle()
        .on('error',gutil.log)
        .pipe(source(name))
        .pipe(gulp.dest('./'));

});

// Inject bundle into HTML.
gulp.task('inject', ['clean', 'es6'], function() {

    const target = gulp.src('index.html');
    const sources = gulp.src(path.join(BUILD_DIRECTORY, '*.js'), {read: false});
    return target.pipe(inject(sources))
        .pipe(gulp.dest(BUILD_DIRECTORY));

});

// Delete the old bundle.
gulp.task('clean', function () {
    return del(path.join(BUILD_DIRECTORY, 'bundle*.js'));
});

每次 运行 inject 都会创建一个新的捆绑文件。 clean 任务会删除所有旧的捆绑文件,否则您最终会收到大量这些文件。

请注意,我假设您的 index.htmlmain.js 位于目录的根目录中。

编辑

抱歉忘了 HTML:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

    <!-- inject:js -->
    <!-- endinject -->
</body>
</html>

编辑 2

您应该在 gulp 文件中设置 Browsersync。这样你就可以准确地告诉 Browsersync 什么时候发生了变化,而不是让它在那里等待。

gulp.task('serve', ['inject'], function() {

    // Start browser sync after "inject" has finished.
    browserSync.init({
        server: {
            baseDir: './dist'
        }
    });

    // When the watch is triggered, call "reload". That will call "inject" and then let 
    // Browsersync know a change has occurred.
    gulp.watch('*.js', ['reload']);

});

gulp.task('reload', ['inject'], function() {
    browserSync.reload();
});

serve 任务现在编译所有 JavaScript,启动 Browsersync 并开始监视 JavaScript 文件更改(上面的示例只监视根目录,您可能必须更改适合您的项目)。一旦 gulp.watch() 发现变化,它将调用 reload 任务,后者调用 inject 任务,然后重新加载 Browsersync。

reload 本身并没有做太多事情,但请注意它首先调用 inject。因此它将等待该任务完成,然后再重新加载 Browsersync。