我有一个由我基于 generator-webapp
构建的 yeoman 生成器支持的咕噜咕噜的项目,如果有任何帮助,你可以在 GitHub 上找到它
繁琐的项目使我们承担了grunt-usemin
任务。
我的项目涉及建立一个多语言网站,为了保持清洁,我决定将所有用一种语言编写的页面放在该语言的 2 个字母的短代码之后的文件夹名称中。
| project/
|--dist/
|----en/
|------index.html
|------404.html
|------...
|----fr/
|------index.html
|------404.html
|------...
这些文件由车把模板制成,并用assemble
处理。在布局中,我有用于usemin
的构建块,例如
<!-- build:css(.tmp) styles/main.css -->
<link rel="stylesheet" href="../styles/main.css">
<!-- endbuild -->
<!-- build:js scripts/vendor/modernizr.js -->
<script src="../bower_components/modernizr/modernizr.js"></script>
<!-- endbuild -->
在一个完美的世界中,这将转化为
<link rel="stylesheet" href="../styles/main.css">
<script src="../scripts/vendor/modernizr.js"></script>
而是显示
<link rel="stylesheet" href="styles/main.css">
<script src="scripts/vendor/modernizr.js"></script>
这在我的情况下不太理想。Gruntfile.js
的相关部分如下所示
useminPrepare: {
options: {
dest: '<%= yeoman.dist %>'
},
html: [
'<%= yeoman.app %>/fr/{,*/}*.html',
'<%= yeoman.app %>/en/{,*/}*.html'
]
},
usemin: {
options: {
dirs: ['<%= yeoman.dist %>']
},
html: [
'<%= yeoman.dist %>/fr/{,*/}*.html',
'<%= yeoman.dist %>/en/{,*/}*.html'
],
css: ['<%= yeoman.dist %>/styles/{,*/}*.css']
}
我尝试使用basedir
选项通过将其设置为 <%= yeoman.dist %>
并将构建块更改为
<!-- build:css(.tmp) ../styles/main.css -->
<link rel="stylesheet" href="../styles/main.css">
<!-- endbuild -->
<!-- build:js ../scripts/vendor/modernizr.js -->
<script src="../bower_components/modernizr/modernizr.js"></script>
<!-- endbuild -->
但不幸的是,无法获得适当的输出。
更具体地说,第一个没有改变任何东西,第二个文件夹scripts
,styles
在层次结构中输出一个级别太高
| project/
|--app/
|--dist/
|--styles/
|--scripts/
而不是
| project/
|--app/
|--dist/
|----styles/
|----scripts/
有人碰巧知道该怎么做吗?这似乎是一个相当简单的用例,但我无法通过谷歌、GitHub 或 SO 找到我需要的帮助......
你可以通过这种方式实现你需要的东西:
网页文件:
<!-- build:css styles/main.css -->
<link href='../styles/css/style.css' rel='stylesheet' type='text/css'>
<link href='../styles/css/responsive.css' rel='stylesheet' type='text/css'>
<link href="../styles/css/skins/welld.css" rel='stylesheet' type='text/css' id="skin-file">
<!-- endbuild -->
咕噜咕噜.js
useminPrepare: {
options: {
dest: '<%= yeoman.dist %>/'
},
html: ['<%= yeoman.app %>/snippets/head.html','<%= yeoman.app %>/snippets/tail.html']
},
usemin: {
options: {
dirs: ['<%= yeoman.dist %>/'],
blockReplacements: {
css: function (block) {
return '<link rel="stylesheet" href="../' + block.dest + '"/>';
},
js: function (block) {
return '<script src="../' + block.dest + '"></script>';
}
}
},
html: ['<%= yeoman.dist %>/{,*/}*.html'],
css: ['<%= yeoman.dist %>/styles/{,*/}*.css']
}
关键解决方案位于 usemin 任务的blockReplacements
选项中。基本上,该任务会将您的文件放在 <%= yeoman.dist %>/styles/main.css 下,而您的 html 将放在 <%= yeoman.dist %>/en/somefileinEnglish.html 下,并且此文件中每个 'styles/main.css' 实例都将替换为 '../styles/main.css',添加正确的相对路径。
作为额外的提示,如果您正在构建多语言网站,您可能需要考虑在构建时使用 grunt-i18n 来翻译您的文件,这样您就不需要为每种语言维护不同的 html 文件。
我正在构建自己的 Grunt 脚手架,我对这个问题感到沮丧。我设法创建了一个解决方法,我想与您分享。
我想用我自己的一个例子来说明他的问题背后的原因以及我是如何设法解决的。假设我的目录结构如下:
| in/
+---- pages/
| +---- login.html
+---- js/
| +---- s1.js
| +---- s2.js
+---- index.html
| out/
| Gruntfile.js
in/
是我所有源文件所在的位置,out/
是dest
目录,所有输出文件都将存储在其中。假设我想将s1.js
导入login.html
,我会写这样的东西:
<!-- build:js ../js/login.js -->
<script src="../js/s1.js"></script>
<!-- endbuild -->
在这里,usemin 块执行简单的字符串替换,因此输出路径应该正好是我想要链接输出文件的位置。当不是让login.js
降落在out/js/login.js
,而是使用minPrepare最终将其降落在js/login.js
时,就会出现问题。这背后的原因是 useminPrepare 只是在dest
(out
(和输出路径(../js/login.js
(之间执行路径连接,而它应该对找到 HTML 文件的位置执行路径连接。
为了解决此问题,请注意,如果我将dest
设置为out/pages
哪个尊重找到login.html
的位置,它将正常工作。但请注意,如果index.html
以类似的方式导入js/s2.js
,那么就会搞砸。因此,为了解决这个问题,我们需要创建一个 useminPrepare 目标,用于使用 dest: "out"
index.html
,另一个目标用于使用 dest: "out/pages"
login.html
。因此,我的useminPrepare配置现在看起来像这样:
"useminPrepare": {
t1: {
dest: "out",
files: [{src: ["in/*.html"]}],
...
},
t2: {
dest: "out/pages",
files: [{src: ["in/pages/*.html"]],
....
}
}
所有目标都必须运行。现在你可能会说;如果我在其他子目录下有更多的 HTML 文件怎么办?这是否意味着我必须为找到 HTML 文件的每个目录创建一个目标?这是屁股上的痛苦和愚蠢。是的!我同意。所以我写了一个非常特别的咕噜咕噜的任务来帮忙。我称它为useminPreparePrepare我故意把它命名为愚蠢的,因为它是愚蠢的。我真的希望有一天当usemin人解决这个问题时摆脱这项工作。顾名思义,useminPreparePrepare为useminPrepare准备配置。它自己的配置镜像useminPrepare(事实上,大多数配置只是简单地复制过来(,只有一个例外;您必须添加一个指向所有源文件所在的源根目录的 src
属性,以便它可以找出源根目录和 HTML 文件之间的相对路径。它将基本上执行我上面提到的内容。另外,它对暂存目录也执行相同的操作,因此暂存文件不会脱离暂存目录。您甚至可以在useminPreparePrepare中有多个目标,它将复制您运行的目标的选项。
为了使用此方法,您首先必须导入useminPreparePrepare。我没有把它放在 npm 上,所以你只需要复制并粘贴它。我不介意。然后只需将 useminPrepare 配置重命名为 useminPreparePrepare,并添加src
属性。对于上面的示例,src: "in"
.然后,您需要使用您通常想要的任何目标运行 useminPrepare,然后立即运行 useminPrepare而不指定目标,以便所有目标都将运行。给定上面的例子 Grunt 配置可能看起来像这样:
"useminPreparePrepare": {
html: "in/**/*.html", // All HTML files under in/ and its subdirectories.
options: {
src: "in",
dest: "out",
....
}
},
"copy": {
html: { // Copies all HTML files from in/ to out/ preserving their relative paths.
files: [{
expand: true,
cwd: "in",
src: ["**/*.html"],
dest: "out"
}
]
}
},
"usemin": {
html: "out/**/*.html", // Process all HTML files under out/ and its subdirectories.
...
}
您可以看到上面的配置非常简单,可以递归地将所有 HTML 文件包含在源目录下。 useminPrepare处理所有愚蠢的解决方法,同时看起来就像useminPrepare一样。
我希望这有帮助!
我的解决方案是手动修改 grunt-usemin 插件。
在您喜欢的文本编辑器中打开node_modules/grunt-usemin/fileprocessor.js
。在第 152 行附近的某个地方找到:
if (assetSearchPath && assetSearchPath.length !== 0) {
this.file.searchPath = assetSearchPath;
}
并将其替换为:
if (assetSearchPath && assetSearchPath.length !== 0) {
this.file.searchPath.splice(0, 0, assetSearchPath);
}
默认情况下,this.file.searchPath
是一个包含当前文件的绝对路径的数组。用 ['dist']
覆盖它是没有意义的,最好在数组前面加上"dist"。这样,如果在"dist"目录中找不到项目,则可能会得出结论,路径是相对的或错误的。因此,我们使用 searchPath
数组中的第二个值来查找文件,如果它是相对路径 - 我们得到我们想要的。
我使用了多个目标,如下所示:
useminPrepare: {
target1 : {
src : ['target1/*.html'],
options : {
dest: 'out'
}
},
target2 : {
src : ['target2/folder/*.html'],
options : {
dest: 'out/subfolder'
}
}
},
然后在 HTML 块中,您可以执行以下操作:
<!-- build:js ../subfolder/script.js -->
<script src="../subfolder/scripts/main.js></script>
<!-- endbuild -->
我看到了很多关于这个问题的问题,但没有真正的答案。在我的项目中,我已经将"dist"文件夹映射到"/static"服务器端。所以我不需要计算索引.html中的相对路径。
但是,问题仍然存在于usemin。
<!-- build:css(.tmp) static/css/main.css -->
<link rel="stylesheet" href="css/main.css">
<!-- endbuild -->
USEmin 文件将以 dist/static/css/main.css
编写
HTML 将显示错误(但预期(的路径
<link rel="stylesheet" href="static/css/main.css">
我发现的唯一解决方法是不要触摸 usemin 块,运行 grunt 并手动更新路径。
如果我正确理解了您的问题,我认为您需要"root"选项:
{
useminPrepare: {
html: 'html/index.html',
options: {
root: 'app'
dest: 'dist'
}
}
}
虽然索引.html在html/文件夹中,但文件查找将来自app/而不是html/
我相对于模板制作了usemin块。
我有一个这样的结构:
app/ - webroot source (devmode)
app/views/layouts - layouts for server-generated pages (also has usermin tags init)
app/js - source javascript
dist/ - production build dir
我让我的 html 看起来像这样 app/layouts/main.html:
<!-- build:js js/static.min.js -->
<script src="../../js/controllers/StaticCtrl.js"></script>
<script src="../../js/directives/backImg.js"></script>
<script src="../../js/smooth-scroll.js"></script>
<!-- endbuild -->
在开发上(没有使用,只是提供文件("../../"巧妙地解析为"/",因此它仍然有效。 这样,您无需在开发时进行预处理(使用监视任务或其他任何内容(。
useminPrepare: {
loyalty: {
src: '<%= loyalty.app %>/Views/index.tpl',
options: {
dest: '.',
flow: {
html: {
steps: {
js: ['concat', 'uglifyjs'],
css: ['cssmin']
},
post: {}
}
}
}
}
},
<!-- build:css /resources/v4/css/loyalty/index.css -->
<link rel="stylesheet" href="../Resources/css/main.css">
<link rel="stylesheet" href="../Resources/css/product.css">
<link rel="stylesheet" href="../Resources/css/use_code.css">
<!-- endbuild -->
在 gruntfile 中使用 '." 作为目的地。
我为相对路径做了一个错误修复。https://www.npmjs.com/package/grunt-usemin-fix
您可以将更改复制并粘贴到使用源 min,以使用相对路径