【问题标题】:Versioning bundle file版本控制捆绑文件
【发布时间】:2016-07-26 10:46:00
【问题描述】:

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

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

<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 任务之后立即重新加载。

谢谢!

【问题讨论】:

    标签: javascript reactjs gulp bundle babeljs


    【解决方案1】:

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

    您可以使用 node-randomstring 之类的东西来生成文件名(或者有很多其他方法可以做到这一点),然后使用 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 之前等待该任务完成。

    【讨论】:

    • 我正在使用 BrowserSync,你是对的,它更好。但它有一个问题,我不知道为什么。你能看看我的更新吗?谢谢
    • @TrongLamPhan 我已经编辑了我的答案。我不完全确定您是否还需要inject 任务,因此您可能想在触发gulp.watch() 后立即调用es6 任务而不是inject。但无论如何,希望你能从我的回答中得到灵感。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多