【问题标题】:AngularJS breaks when minified while using a service在使用服务时缩小 AngularJS 会中断
【发布时间】:2014-09-15 03:28:54
【问题描述】:

好的,我对 AngularJS 还很陌生,所以如果这很简单,请不要笑。我正在尝试关注Todd Motto's Opinionated AngularJS Styleguide for Teams。我知道它看起来不太像,因为我试图减少代码。我正在使用 Grunt 来丑化我的代码。如果我关闭修饰,它会起作用。否则,我会收到错误消息:

Error: [$injector:unpr] Unknown provider: aProvider <- a

我知道这是因为名称被破坏了,所以它不知道将其映射到什么,但我不知道如何/在哪里注入正确的名称。我试图追踪它。我认为是当我们尝试解析路由时,DataService 正在被注入,并且因为我们的 DataService 没有注入,我认为它被破坏了。

我已尝试尽可能减少我的代码。这也依赖于 angular 和 angular-route,以及一个名为 data.json 的文件(可以是任何东西,这并不重要)。然后运行grunt debug

如果我遗漏了什么,请告诉我,感谢您的宝贵时间。

文件结构

├── data.json
├── gruntfile.js
├── index.html
└── js
    ├── app
    │   └── app.js
    └── vendor
        ├── angular-route.js
        └── angular.js

gruntfile.js

module.exports = function(grunt) {
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        uglify: {
            debugMine: {
                options: {
                    wrap: true,
                    sourceMap: true,
                    mangle: false,
                },
                files: { 'js/production.min.js': [
                    'js/app/app.js',
                ]}
            },
            debugVendor: {
                files: { 'js/vendor.min.js': [
                    'js/vendor/angular.js',
                    'js/vendor/angular-route.js',
                ]}
            }
        },
        connect: {
            server: {
                options: {
                    port: 8000,
                }
            }
        },
        watch: {
            myscripts: {
                files: ['js/app/**'],
                tasks: ['uglify:debugMine'],
            },
            options: {
                livereload: true,
                spawn: false
            },
            vendorscripts: {
                files: ['js/vendor/**'],
                tasks: ['uglify:debugVendor'],
            }
        }
    });

    grunt.loadNpmTasks('grunt-contrib-connect');
    grunt.loadNpmTasks('grunt-contrib-uglify');
    grunt.loadNpmTasks('grunt-contrib-watch');

    grunt.registerTask('debug',
                        'Create a debug build of the code',
                        [
                            'uglify:debugMine',
                            'uglify:debugVendor',
                            'connect:server',
                            'watch',
                        ]);
};

index.html

<!DOCTYPE html>
<html ng-app="app">
    <head>
        <meta charset="utf-8">
        <title>Mangled Names Test</title>
    </head>
    <body>

        <h2>I'm above the content</h2>
        <hr>
        <!-- Begin Content -->
        <div ng-view></div>
        <!-- End Content -->
        <hr>
        <h2>I'm below the content</h2>

        <!-- Begin Release Scripts -->
        <script src='js/vendor.min.js'></script>
        <script src='js/production.min.js'></script>
        <!-- End Release Scripts -->
    </body>
</html>

app.js

console.log('Define functions that make up app');

function DataService($http) {
    console.log('Setting up data service');
    var DataService = {};

    DataService.getData = function() {
        console.log('In DataService.getData, getting data');
        return $http.get('/data.json');
    };

    return DataService;
}

function DocumentCtrl(data) {
    console.log('In DocumentCtrl, check data');
    var self = this;
    self.data = data;
}

DocumentCtrl.resolve = {
    data: function(DataService) {
        console.log('Call DataService.getData()');
        return DataService.getData();
    },
}

function RouteConfig($routeProvider) {
    console.log('Define routes');
    $routeProvider
        .when('/', {
            template: "<h4>I'm in the content and above the data</h4><hr>{{docCtrl.data}}<hr><h4>I'm in the content and below the data</h4>",
            controllerAs: 'docCtrl',
            controller: 'DocumentCtrl',
            resolve: {
                data: function(DataService) {
                    console.log('Call DataService.getData()');
                    return DataService.getData();
                },
            }
        })
        .otherwise({ redirectTo: '/' })
}

console.log('Define module');

angular
    .module('app', ['ngRoute'])
    .factory('DataService', ['$http', DataService])
    .controller('DocumentCtrl', ['data', DocumentCtrl])
    .config(['$routeProvider', RouteConfig]);

【问题讨论】:

  • 在控制器中试试这个 .controller('DocumentCtrl', ['DataService', DocumentCtrl])

标签: angularjs gruntjs uglifyjs


【解决方案1】:

mangle:false 添加到uglify.debugVendor.options 可能会解决它。如果没有,那么您可能需要将供应商和您的文件一起编译,以便 uglify 可以在同一范围内使用它们。

    uglify: {
        // ...
        debugVendor: {
            options: {
                mangle: false,
            },
        }

【讨论】:

    【解决方案2】:

    您的服务名称是DataService,因此您的配置中的声明应该具有相同的名称,例如:

    .controller('DocumentCtrl', ['DataService', DocumentCtrl])
    

    从上面的示例中:

    angular
        .module('app', ['ngRoute'])
        .factory('DataService', ['$http', DataService])
        .controller('DocumentCtrl', ['DataService', DocumentCtrl])
        .config(['$routeProvider', RouteConfig]);
    

    【讨论】:

    • 是的,同意这一点,OP 在此处查看关于缩小的注释docs.angularjs.org/tutorial/step_05 或者使用 ng-annotate grunt 任务为您执行此操作。
    • 在我链接的那个风格指南中,他谈到在调用控制器之前使用 resolve 来获取数据,而不是在控制器中获取数据:github.com/toddmotto/angularjs-styleguide#routing-resolves 我希望它在调用控制器之前解决。此外,即使我将“DataService”添加到我的控制器定义中,它仍然会因修改而中断。
    【解决方案3】:

    uglify 将 angularjs 服务名称更改为 a,b, .. .所以你必须改变 uglify 选项:

    options: {
        mangle: false,
    },
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-02-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-13
      • 1970-01-01
      • 1970-01-01
      • 2013-08-24
      • 1970-01-01
      相关资源
      最近更新 更多