一个js文件中的所有代码与将代码分隔成多个js文件

时间:2013-10-28 11:21:20

标签: javascript code-separation

到目前为止,我的项目中只有一个javascript文件,其中包含大量功能,其中只有少数功能被多个网页使用。随着涉及的代码量的增加,我可以看到文件变得混乱而且太长了。我正在考虑为每个网页提供一个单独的javascript文件,以便:

  1. 我不需要加载一个巨大的javascript文件,即使是那些很少使用它的页面。
  2. 该文件不会变得更加混乱
  3. 但我不知道这是否会产生任何我不知道的负面影响。

4 个答案:

答案 0 :(得分:1)

较少的文件会导致代码不太干净,这反过来意味着编码速度变慢,难以调试。 更多文件意味着更多HTTP请求和更慢的网站。因此,要开发尽可能多的文件,以便组织代码并保持开发的可管理性。

答案 1 :(得分:1)

拥有多个文件确实可以帮助您整理好事情,但同时需要浏览器向服务器发出多个请求,这可能会影响网站加载时间。

这就是许多人现在使用RequireJS等工具的原因。

简而言之,它允许您根据需要定义任意数量的小模块(每个模块都在单独的文件中),然后它将异步加载它们。

如果你将它与一些构建工具(如Grunt)结合使用,你可以拥有一个只加载两个文件的网页(RequireJS库和你的JS文件,即main.js),但是main.js将是连接许多较小模块的结果。

通过这种方式,您可以将请求的数量保留在minium中,同时,您的代码将以小模块进行组织和拆分成本?您引入了一个额外的构建步骤。但是,使用grunt-contrib-watch等工具可以进一步自动化此构建步骤。


以下是使用一个main.js文件并依赖于将从Google CDN加载的jQuery的网站的几个代码段:

首先, main.js :这是一个RequireJS模块(它是一个AMD模块),看起来像:

// Tell RequireJS that jQuery dependency should be loaded from the given URL.
// Without this, RequireJS would try to find jQuery.js file locally.
requirejs.config({
  paths: {
    'jQuery': '//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min',
  },
  shim: {
    'jQuery': {'exports': 'jQuery'},
  }
});

// You define that the module below depends on jQuery and two custom modules.
define(['jQuery', 'module1', 'module2'], function ($, Module1, Module2) {
  // Here you can access $, Module1 and Module2
});

然后使用Grunt的grunt-contrib-requirejs插件,配置类似于( Gruntfile.js ):

requirejs: {
  compile: {
    options: {
      baseUrl: 'src/js',         // modules dir, which contains main.js, module1.js etc.
      out: 'static/js/main.js',  // output file
      name: 'main',
      paths: {
        'jQuery': 'http://lorem.ipsum1'  // jQuery will be loaded separately from CDN
      },
      optimize: 'uglify2'        // minify output file
    }
  }
}

最后,加载RequireJS脚本并告诉它使用main.js文件作为您网站的入口点( index.html ):

<script src="js/require.min.js" data-main="js/main.js"></script>

答案 2 :(得分:1)

这里有很多选项,主要集中在组织文件方面,值得考虑使用像require.js 这样的库,如果你正在做的事情相当大。然而,这适用于应用程序,即使您可以轻松地将其用于其他事项,也就是您将代码重构为独立模块,这在您的案例中可能是合理的,也可能是不合理的。

然而,如果我们所讨论的javascript是紧密与页面内容相结合,因此在其设置中不能重复使用其他页面,使用内联{{1标签而不是外部javascript文件。

最后一个注意事项,require.js或任何带有多个javascript的设置会给http请求带来轻微的开销,但我不会太担心。 Require.js或类似的库甚至会为你加载这个异步,所以总而言之它可能比一个巨大的文件更有效,它可能不会用于任何给定访问者的大部分(尽管这取决于访问者是否最终会访问所有页面。)

答案 3 :(得分:0)

现在,我用一组逻辑文件夹(服务,控制器,Lib等)在分离的文件中开发我的所有javascript。

但是我在Node.js上使用Gulp和Bower。注意,我没有将Node.JS用作我的服务器端代码,只是我的前端资产。可以将其视为客户端资产的分发工具。我使用Gulp-Watch监视我的SRC文件夹,并在处理源代码时自动转换最终的javascript文件。

因此,我得到了将所有内容逻辑分离的好处,但仍然可以获得用于生产的单个压缩JS文件的性能。

以下是bower.json文件的示例:

{
  "name": "MyApp",
  "private": true,
  "dependencies": {
    "jquery": "2.2.4",
    "bootstrap": "v4.0.0-alpha.3",
    "angular": "^1.5.8",
    "font-awesome": "fontawesome#^4.6.3",
    "angular-ui-router": "^0.3.1",
    "angular-cookies": "^1.5.8",
    "angular-ui-select": "^0.19.4",
    "angular-ui-tree": "^2.17.0",
    "angular-toastr": "^2.0.0",
    "angular-animate": "^1.5.8",
    "angular-sanitize": "^1.5.8",
    "angular-chart": "^0.5.0",
    "angular-loading-bar": "^0.9.0",
    "angular-messages": "^1.5.8"
  },
  "devDependencies": {}
}

这是Gulp-File

/// <binding Clean='clean' />
"use strict";

var gulp = require("gulp");
var sass = require("gulp-sass"); //Syntactically Awesome Style Sheets
var sourcemaps = require('gulp-sourcemaps'); //Generate source maps for css and js
var autoprefixer = require('gulp-autoprefixer'); //auto prefix browser specific css 
var cleanCss = require('gulp-clean-css'); //minimize css
var rename = require('gulp-rename'); //rename file in gulp stream
var concat = require('gulp-concat'); //concat mutliple files in gulp stream into one
var runSequence = require('run-sequence'); //run mutliple gulp taxes in parrellel or sequence
var uglify = require('gulp-uglify'); //minimize js

var webroot = "./wwwroot/"; //the root folder where the css and js is going

var paths = {
    css: webroot + "css/", //path to my css
    scss: webroot + "scss/", //path to my scss src files
    destJs: webroot + "js/", //path to my js source files (also the destination)
    lib: webroot + "/lib/" //path to my lib folder for storing libraries
};

//build both the dev and production styles
gulp.task('build-styles', function (done) {
    return runSequence(["build-styles-dev", "build-styles-prod"]);
});



//sass transforms all my scss files individually (producing separate css files for each library I am using)
    gulp.task('build-styles-dev', function () {
        var sassOptions = {
            errLogToConsole: true,
            outputStyle: 'expanded',
            sourceMap: true
        };
        return gulp.src([ //include all my libraries css files that isn't sass based in the front of the stream
                paths.lib + '/angular-loading-bar/build/loading-bar.css',
                paths.lib + '/angular-toastr/dist/angular-toastr.css',
                paths.lib + '/angular-ui-select/dist/select.css',
                paths.lib + '/angular-ui-tree/dist/angular-ui-tree.css',
                paths.lib + '/tether/dist/css/tether.css',
                paths.lib + '/tether/dist/css/tether-theme-basic.css',
                paths.scss + '/site.scss' //my sass file (does imports etc in it)
        ])  
            .pipe(sass({ errLogToConsole: true, outputStyle: 'expanded', sourceMap: true }).on('error', sass.logError))
            .pipe(autoprefixer()) //autoprefix browser specific css
            .pipe(gulp.dest(paths.css)) //output all the sass and auto prefixed css files based on the source
            .resume();
    });

    //same as above task except this one doesn't output the individual files.  It concats them all together into one file, compresses it, and generates the source maps for it.
    gulp.task('build-styles-prod', function () {
        var sassOptions = {
            errLogToConsole: true,
            outputStyle: 'expanded',
            sourceMap: true
        };
        return gulp.src([
                paths.lib + '/angular-loading-bar/build/loading-bar.css',
                paths.lib + '/angular-toastr/dist/angular-toastr.css',
                paths.lib + '/angular-ui-select/dist/select.css',
                paths.lib + '/angular-ui-tree/dist/angular-ui-tree.css',
                paths.lib + '/tether/dist/css/tether.css',
                paths.lib + '/tether/dist/css/tether-theme-basic.css',
                paths.scss + '/site.scss'
        ])
            .pipe(sass({ errLogToConsole: true, outputStyle: 'expanded', sourceMap: true }).on('error', sass.logError))
            .pipe(autoprefixer())
            .pipe(concat("compiled.css"))
            .pipe(gulp.dest(paths.css))
            .pipe(sourcemaps.init({ loadMaps: true }))        
            .pipe(cleanCss())
            .pipe(rename({ suffix: '.min' }))        
            .pipe(sourcemaps.write('.'))        
            .pipe(gulp.dest(paths.css))
            .resume();
    });

    //grabs all the library scripts and compresses them into one js file
    gulp.task('build-scripts', function () {
        return gulp.src([
            paths.lib + 'jquery/dist/jquery.js',
            paths.lib + 'tether/dist/js/tether.js',
            paths.lib + 'angular/angular.js',
            paths.lib + 'angular-messages/angular-messages.js',
            paths.lib + 'angular-animate/angular-animate.js',
            paths.lib + 'angular-cookies/angular-cookies.js',
            paths.lib + 'angular-chart/angular-chart.js',
            paths.lib + 'angular-loading-bar/build/loading-bar.js',
            paths.lib + 'angular-toastr/dist/angular-toastr.js',
            paths.lib + 'angular-sanitize/angular-sanitize.js',
            paths.lib + 'angular-ui-router/release/angular-ui-router.js',
            paths.lib + 'angular-ui-select/dist/select.js',
            paths.lib + 'angular-ui-tree/dist/angular-ui-tree.js',
            paths.lib + 'bootstrap/dist/js/bootstrap.js',
            paths.js + 'app.js', //Load app.js first
            paths.js + 'services/**/*.js', //Load all angular services next
            paths.js + 'directives/**/*.js', //load directives after services
            paths.js + 'controllers/**/*.js', //load angular controllers last after services and directives
            paths.js + 'appLast.js', //A tail script I have load last for end of page logic, preventing the need for me to use document ready since this loads in the page footer.
        ])
            .pipe(sourcemaps.init())
            .pipe(gulp.dest(paths.destJs)) //output all the files individually (so file names need to be unique accross the whole system, generally not a problem)
            .pipe(concat('scripts.js')) //concat all the scripts together into one file called scripts.js
            .pipe(uglify()) //minimize all the scripts
            .pipe(rename({ suffix: '.min' })) //rename to scripts.min.js
            .pipe(sourcemaps.write('.')) //write the source maps
            .pipe(gulp.dest(paths.destJs)); //output scripts.min.js
    });

我的gulp文件中缺少的部分是应用程序脚本,它看起来像这样(尚未为此应用程序完成它)。

相关问题