如何通过grunt contrib uglify按顺序缩小js文件
how to minify js files in order via grunt-contrib-uglify?
我有一个如下目录:
/文件夹/b.js
/folder/jQuery.js
/文件夹/a.js
/folder/sub/c.js
我想在一个js文件中缩小所有这些js文件,按顺序:
jQuery.js->a.js->b.js->c.js
问:
1.我怎样才能通过咕哝的方式来完成它?(事实上,有很多文件,单独指定所有源文件路径是不切实际的)
2.btw,如何在调试时获得未缩小的文件,在发布时获得缩小的单个文件,并且无需更改html中的脚本标记(以及如何编写脚本标记)?
好问题!
1) Uglify将对目标文件中的函数进行重新排序,使函数定义位于顶部,函数执行位于底部,但它似乎将保留函数执行的顺序。
这意味着,如果您确保在Gruntfile中的Uglify配置中首先提到jQuery,那么jQuery运行以定义其全局函数的函数将被放在第一位。
我使用这个配置:
uglify: {
options: {
sourceMap: true
},
build: {
files: {
'public/all.min.js': ['public/js/vendor/jquery-1.10.2.min.js', 'public/js/*.js'],
}
}
}
2) 我认为没有一种确切的方法可以做到这一点。这取决于你有什么样的web框架、模板框架和什么样的需求。我使用快递+翡翠,在我的主要翡翠布局中,我有:
if process.env.NODE_ENV === 'production'
script(src='/all.min.js')
else
script(src='/js/vendor/jquery-1.10.2.min.js')
script(src='/js/someScript.js')
script(src='/js/otherScript.js')
在我的包.json中,我有:
"scripts": {
"postinstall": "grunt"
},
这意味着,当我在deploy(在Heroku上)上运行npm install
时,会运行grunt来缩小/concat文件,当应用程序使用NODE_ENV=production
启动时,会使用缩小的客户端javascript。在本地,我得到了原始的客户端java脚本,以便于调试。
两个缺点是:
- 我必须保持脚本文件的两个列表同步(在Gruntfile和layout.js中)。我通过在Gruntfile中使用
*.js
来解决这个问题,但这可能不适合所有人。您可以将javascript的列表放在Gruntfile中,并由此创建一个jade模板,但对于大多数项目来说,这似乎有些过头了 - 如果你不信任你的Grunt配置,你基本上必须在本地使用
NODE_ENV=production
测试运行应用程序,以验证缩小是否按你的预期工作
这可以使用以下Grunt任务来完成:
- https://github.com/gruntjs/grunt-contrib-concat连接文件
- https://github.com/gruntjs/grunt-contrib-uglify迷你型串联文件
编辑
我通常使用Grunt contrib-concat通过Grunt串联任务运行所有文件。然后我有另一个任务,使用grunt contrib uglify对连接的文件进行uglify。
你可能不会喜欢这样,但最好的方法是将js源文件定义为AMD模块,并使用Requirej来管理它们的加载顺序。grunt contrib requirejs任务将递归依赖树,并按必要的顺序将js文件连接到一个大的js文件中。然后,您将使用uglify(实际上r.js内置了uglify)来缩小大文件。
https://github.com/danheberden/yeoman-generator-requirejs有一个很好的示例gruntfile和模板js文件可供使用。
编辑
我最近开始使用CommonJS模块而不是AMD,因为它更接近ES6模块规范。通过Browserify运行CommonJS模块可以获得相同的结果(1个大的composed+级联的js文件)。grunt和gullow都有插件可以为您管理任务。
编辑
我想补充一点,如果你的网站是使用ES6编写的,那么Rollup是最好的新连接包。除了绑定文件外,它还将执行树抖动,删除通过import
语句包含的库的部分。这将减少你的代码库,使其满足你的需求,而不会出现你永远不会使用的代码膨胀。
我不认为你可以单独使用uglify任务来做到这一点,但你有很多选择,可能会得到你想要的结果。
一个可能的工作流程是首先将文件按顺序连接到一个文件中,然后将连接的文件通过uglify。你可以在Gruntfile中定义concat的顺序,也可以在其中一个插件上使用:
第一个是https://github.com/yeoman/grunt-usemin,您可以在HTML文件中指定顺序,在脚本块周围放置一些注释。谷歌的人做了它,使用起来很舒服。
第二个是https://github.com/trek/grunt-neuter,在这里你可以用require定义一些依赖项,但不需要大量的require.js。它需要在js代码中进行更改,所以可能不喜欢它。我选择选项一。
我遇到了同样的问题。一个快速的解决方案就是更改文件名-我使用了1.jquery.min.js
、2.bootstrap.min.js
等。
这可能与您的问题有很大关系,但我想要类似的东西。只有我的订单在以下方面很重要:
我用通配符(['vendor/**/*.js']
)加载所有供应商文件(angular、jquery和它们各自的相关插件)。但有些插件的名称使它们在angular和jquery之前加载。解决方案是先手动加载它们。
['vendor/angular.js', 'vendor/jquery.js', 'vendor/**/*.js]
幸运的是,angular和jquery句柄加载两次就足够了编辑:虽然两次加载这样大的库并不是最好的做法,但会导致缩小后的文件出现不必要的膨胀(感谢@Kano指出这一点!)
另一个问题是客户端js-顺序很重要,因为它要求在加载所有依赖项后最后加载主应用程序文件。解决方案是排除然后包括:
['app/**/*.js', '!app/app.js', 'app/app.js']
这可以防止app.js
与所有其他文件一起加载,并且只有在最后才包括它。
看起来您的问题的第二部分仍然没有答案。但让我一个接一个地试试。
首先,您可以将大量的js文件连接并丑化为一个文件,正如前面的concat答案所解释的那样。还应该可以使用https://github.com/gruntjs/grunt-contrib-uglify因为它似乎确实有通配符。您可能需要尝试使用"expand=true"选项和通配符。这就解决了你的第一个问题。
对于第二部分,假设您加入并丑化了big-ugly.js
现在,在您的html中,您可以添加以下指令:
<!-- build:js:dist big-ugly.js -->
<script src="js1.js"></script>
<script src="js2.js"></script>
<!-- etc etc -->
<script src="js100.js"></script>
<!-- /build -->
然后在https://www.npmjs.com/package/grunt-processhtml作为你繁重工作的一部分。
这个预处理器将用替换整个块
<script src="big-ugly.js"></script>
这意味着html文件在语义上是等价的——在grunt作业之前和之后;即,如果页面以原生形式正常工作(用于调试),则转换后的页面必须在发出咕哝声后正常工作,而无需手动更改任何标记。
这是@1469的答案,但他没有明确说明为什么这样做。使用concat将所有js文件放在一个文件中,这个模块按照文件名的顺序来做这件事,所以我根据顺序为文件名加了一个前缀。我相信它甚至还有其他的订购选择。
concat: {
js: {
options: {
block: true,
line: true,
stripBanners: true
},
files: {
'library/dist/js/scripts.js' : 'library/js/*.js',
}
}
},
然后使用uglify创建缩小的丑陋版本:
uglify: {
dist: {
files: {
'library/dist/js/scripts.min.js': [
'library/js/scripts.js'
]
},
options: {
}
}
},
如果您的问题是您有需要按顺序加载的供应商(假设jquery先于任何jquery插件)。我通过将jquery放在它自己的名为"!jquery’,有效地将其放在堆栈的顶部。然后我只是像你平时一样使用concat:
concat: {
options: {
separator: ';',
},
build: {
files: [
{
src: ['js/vendor/**/*.js', 'js/main.min.js'],
dest: 'js/global.min.js'
}
]
}
},
- ajax请求的顺序总是不同的
- 按照选项卡索引的顺序循环一个jQuery选择
- 匹配一个单词,其中候选人可以跨越顺序组(跨度)
- 按顺序添加和删除类
- 按我自己的类克隆另一个元素的内容和顺序
- Javascript-根据赋值顺序,按键合并对象数组
- 2个backbone.js集合,具有相同的模型,但排序顺序不同
- querySelector/getElementByClassName嵌套项的顺序
- 如何在d3上的图形中添加放大和缩小按钮
- 以不同的顺序输出数据
- 重新排列HTML元素的顺序并更改内容
- 在Javascript中列出顺序子集元素
- 是否“;对于的“;循环迭代遵循JavaScript中的数组顺序
- Mongodb$in以与数组中相同的顺序获取结果
- 如何使用phonegap从安卓设备中提取联系人的字母顺序
- 在表单OnChange中交换数字顺序
- 如何按对象反转Angular ngRepeat的顺序's键,这些键是数字键
- 预保存钩子:mongoose中回调的顺序如何
- 如何通过grunt contrib uglify按顺序缩小js文件
- 使用构建顺序缩小 java 脚本的工具