38

我有一些项目使用RequireJS在浏览器中加载单个 JavaScript 模块,但我还没有优化它们。在开发和生产中,应用程序对每个 JavaScript 文件都发出单独的请求,现在我想使用Grunt来解决这个问题。

我试图组合一个简单的项目结构无济于事,所以我想知道是否有人可以为我提供一个工作示例。我的目标如下:

  1. 在开发模式下,通过为每个所需模块发出单独的请求,一切都在浏览器中运行。在开发模式下不需要繁琐的任务或连接。
  2. 当我准备好时,我可以运行一个 grunt 任务来优化(组合)所有使用r.js的 JavaScript 文件并在本地进行测试。一旦我确信优化的应用程序可以正确运行,我就可以部署它。

以下是本次对话的示例结构:

grunt-requirejs-example/
  grunt.js
  main.js (application entry point)
  index.html (references main.js)
  lib/ (stuff that main.js depends on)
    a.js
    b.js
    requirejs/
      require.js
      text.js
  build/ (optimized app goes here)
  node_modules/ (necessary grunt tasks live here)

具体来说,我正在寻找一个可以开始的工作项目结构。我的主要问题是:

  1. 如果这个项目结构有缺陷,你有什么建议?
  2. 我的文件中究竟需要什么grunt.js,尤其是要让 r.js 优化器正常工作?
  3. 如果所有这些都不值得,并且有一种方法可以watch在每次保存文件时使用 grunt 任务在开发模式下自动构建所有内容,那么我全都听好了。我想避免任何会减慢循环从进行更改到在浏览器中看到它的事情。
4

1 回答 1

81

我使用grunt-contrib-requirejs任务来构建基于 require.js 的项目。将其安装在您的项目目录中:

npm install grunt-contrib-requirejs --save-dev

顺便说一句:--save-dev将包添加到您的 package.json 中的开发依赖项中。如果您没有在项目中使用 package.json,请忽略它。

使用以下命令将任务加载到您的 grunt 文件中:

grunt.loadNpmTasks('grunt-contrib-requirejs');

并将配置添加到您的 grunt.initConfig

requirejs: {
  production: {
    options: {
      baseUrl: "path/to/base",
      mainConfigFile: "path/to/config.js",
      out: "path/to/optimized.js"
    }
  }
}

现在您可以将您的 require.js 内容构建到一个文件中,该文件将通过运行 uglifyjs 最小化grunt requirejs

您可以将一组不同的任务捆绑到某种主要任务中,方法是将其添加到您的 grunt 文件中

grunt.registerTask('default', ['lint', 'requirejs']); 

有了这个,你可以简单地输入grunt,grunt 会自动运行带有两个“子任务”的默认任务:lint 和 requirejs。

如果你需要一个特殊的生产任务:像上面那样定义它

grunt.registerTask('production', ['lint', 'requirejs', 'less', 'copy']);

并运行它

grunt production

如果您需要在 requirejs 任务中进行“生产”和“开发”的不同行为,您可以使用所谓的目标。在上面的配置示例中,它已经定义为production. 如果需要,您可以添加另一个目标(顺便说一句,您可以通过在同一级别添加选项对象来为所有目标定义全局配置)

requirejs: {
  // global config
  options: {
    baseUrl: "path/to/base",
    mainConfigFile: "path/to/config.js"
  },
  production: {
    // overwrites the default config above
    options: {
      out: "path/to/production.js"
    }
  },
  development: {
    // overwrites the default config above
    options: {
      out: "path/to/development.js",
      optimize: none // no minification
    }
  }
}

grunt requirejs现在,您可以使用或单独运行它们grunt requirejs:production,或者在不同的任务中定义它们:

grunt.registerTask('production', ['lint', 'requirejs:production']);
grunt.registerTask('development', ['lint', 'requirejs:development']);

现在回答你的问题:

  1. 我肯定会在您的项目中使用子文件夹。在我的例子中,我使用一个“src”文件夹进行开发,该文件夹构建到一个用于生产的“htdocs”文件夹中。我喜欢的项目布局是:

    project/
      src/
        js/
          libs/
            jquery.js
            ...
          appname/
            a.js
            b.js
            ...
          main.js // require.js starter
        index.html
        ...
      build/
        ... //some tmp folder for the build process
      htdocs/
        ... // production build
      node_modules/
        ...
      .gitignore
      grunt.js
      package.json
    
  2. 看上面

  3. 你可以这样做,但我不建议将 requirejs 添加到 watch 任务中,这是一项资源消耗的任务,它会显着降低你的机器速度。

最后但同样重要的是:在玩 r.js 时要非常小心。modules尤其是当您想通过在配置中添加指令来使用 r.js 优化整个项目时。R.js 将在不询问的情况下删除输出目录。如果碰巧它被意外配置为您的系统根目录,r.js 将擦除您的硬盘。请注意,前段时间我在设置我的 grunt 任务时永久删除了我的整个 htdocs 文件夹......keepBuildDir:true在使用 r.js 配置时,请始终添加到您的选项中。

于 2012-12-30T00:16:35.673 回答