【问题标题】:How can I insert content into a file during a gulp build?如何在 gulp 构建期间将内容插入文件?
【发布时间】:2015-06-25 20:09:46
【问题描述】:

我设法使用一个名为 gulp-insert 的 gulp 插件完成了我的任务,如下所示:

gulp.task('compile-js', function () {
  // Minify and bundle client scripts.
  var scripts = gulp.src([
    srcDir + '/routes/**/*.js',
    srcDir + '/shared/js/**/*.js'
  ])
    // Sort angular files so the module definition appears
    // first in the bundle.
    .pipe(gulpAngularFilesort())
    // Add angular dependency injection annotations before
    // minifying the bundle.
    .pipe(gulpNgAnnotate())
    // Begin building source maps for easy debugging of the
    // bundled code.
    .pipe(gulpSourcemaps.init())
    .pipe(gulpConcat('bundle.js'))
    // Buffer the bundle.js file and replace the appConfig
    // placeholder string with a stringified config object.
    .pipe(gulpInsert.transform(function (contents) {
      return contents.replace("'{{{appConfigObj}}}'", JSON.stringify(config));
    }))
    .pipe(gulpUglify())
    // Finish off sourcemap tracking and write the map to the
    // bottom of the bundle file.
    .pipe(gulpSourcemaps.write())
    .pipe(gulp.dest(buildDir + '/shared/js'));

  return scripts.pipe(gulpLivereload());
});

我正在做的是读取我们应用程序的配置文件,该文件由 npm 上的 config 模块管理。使用var config = require('config'); 从服务器端代码获取我们的配置文件很容易,但我们是一个单页应用程序,经常需要访问客户端的配置设置。为此,我将配置对象填充到 Angular 服务中。

这是 gulp 构建之前的 Angular 服务。

angular.module('app')
  .factory('appConfig', function () {
    return '{{{appConfigObj}}}';
  });

占位符位于字符串中,因此对于其他一些首先处理文件的 gulp 插件来说,它是有效的 JavaScript。 gulpInsert 实用程序让我可以像这样插入配置。

.pipe(gulpInsert.transform(function (contents) {
  return contents.replace("'{{{appConfigObj}}}'", JSON.stringify(config));
}))

这可行,但感觉有点 hacky。更不用说它必须缓冲整个捆绑文件,以便我可以执行操作。有没有更优雅的方式来完成同样的事情?最好是一种允许流保持平稳流动而不在最后缓冲整个捆绑包的方法?谢谢!

【问题讨论】:

  • 对此我采取了一些不同的方法。我为每个环境创建了一个 json 文件。 dev.config.js、prod.config.js & 在 gulp dev/prod 构建期间,我确实用适当的 config.js 替换了我的 env.config.js,并且我的 index.html 包括 env.config.js。这感觉比在文件中搜索和替换要干净一些
  • 抱歉,使用缓冲区有什么问题?流式传输也是一种缓冲,但体积更小。但是,我真的怀疑你的整个 bundle.js 是否超过了 1 Mb,这在当今几乎没有。也许,您对构建的整体执行时间不满意。在这种情况下,您应该考虑使用 watch 功能。
  • 这是一个大型企业应用Dimitry。它还不是很大,但肯定会很大。我们使用 gulp 是为了提高性能,这使得构建时间可能比使用 grunt 的相同设置要短得多。我正在注意尽早正确地做事,以便在未来的每一秒都减少。
  • @entre 我确实喜欢这种方法,但我选择了下面 tomtastico 的回答。请随时分享您的解决方案,因为它可以使其他人受益。

标签: javascript angularjs node.js stream gulp


【解决方案1】:

你检查过gulp-replace-task吗?

类似

[...]
.pipe(gulpSourcemaps.init())
.pipe(replace({
  patterns: [{
    match: '{{{appConfigObj}}}',
    replacement: config
  }],
  usePrefix: false
})
.pipe(gulpUglify())
[...]

【讨论】:

  • 不错!根据需要看起来像it does do the replace mid-stream,而不是等待它在最后缓冲。很好的发现:D
  • 这个模块很好用!非常强大的正则表达式+替换功能。
【解决方案2】:

诚然,这也让人感觉有点 hacky,但可能稍微好一点……我在 React 项目中使用 envifygulp-env。你可以这样做。

gulpfile.js:

var config = require('config');
var envify = require('envify');

gulp.task('env', function () {
    env({
        vars: {
            APP_CONFIG: JSON.stringify(config)
        }
    });
});

gulp.task('compile-js', ['env'], function () {
  // ... replace `gulp-insert` with `envify`
});

工厂:

angular.module('app')
  .factory('appConfig', function () {
    return process.env.APP_CONFIG;
  });

【讨论】:

  • 在进行替换之前,envify 是否仍然缓冲整个文件?
  • 老实说,我不确定。我猜“不”,因为 envify 在我的项目中似乎很快,但这只是一个猜测。
  • 您是否最终得到一个包含所有文件内容的变量作为字符串,然后您对其进行替换工作?如果你这样做,那么它会将整个文件缓冲到内存中。我这样做的方式也很快,只是我想坚持 gulp 流模式并尽可能减少每一纳秒。随着时间的推移,这个文件只会越来越大。
  • 我知道你现在如何使用它来解决我的问题了:D。我确实认为它可能在您怀疑的流配置中工作。虽然我认为我宁愿找到他们在模块中使用的逻辑并复制它。那不会感觉很hacky。我去看看:)
  • @MrYellow 工具如 UglifyJS2 将删除这样无法访问的代码。
猜你喜欢
  • 1970-01-01
  • 2017-01-25
  • 2016-08-31
  • 2016-09-29
  • 1970-01-01
  • 2013-02-03
  • 2021-07-02
  • 2023-04-03
  • 1970-01-01
相关资源
最近更新 更多