├── .gitignore
├── .npmignore
├── .gitattributes
├── package.json
├── LICENSE.md
├── README.md
└── index.js
/.gitignore:
--------------------------------------------------------------------------------
1 | /.idea
2 | node_modules/
3 |
4 | .DS_Store
5 | *.db
6 | *.bak
7 | *.tmp
8 | *.cmd
9 | ~*
10 |
11 | upload.py
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | /.idea
2 | /.settings
3 | /.project
4 | /.gitignore
5 | /node_modules
6 | /test
7 | /.tmp
8 |
9 | .DS_Store
10 |
11 | *.db
12 | *.bak
13 | *.tmp
14 | *.cmd
15 | ~*
16 |
17 | upload.py
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
4 | # Custom for Visual Studio
5 | *.cs diff=csharp
6 | *.sln merge=union
7 | *.csproj merge=union
8 | *.vbproj merge=union
9 | *.fsproj merge=union
10 | *.dbproj merge=union
11 |
12 | # Standard to msysgit
13 | *.doc diff=astextplain
14 | *.DOC diff=astextplain
15 | *.docx diff=astextplain
16 | *.DOCX diff=astextplain
17 | *.dot diff=astextplain
18 | *.DOT diff=astextplain
19 | *.pdf diff=astextplain
20 | *.PDF diff=astextplain
21 | *.rtf diff=astextplain
22 | *.RTF diff=astextplain
23 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "fis-postpackager-simple",
3 | "version": "0.0.26",
4 | "description": "a postpackager plugin for fis to auto replace pack resource and auto combine resources",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "repository": {
10 | "type": "git",
11 | "url": "https://github.com/hefangshi/fis-postpackager-simple"
12 | },
13 | "keywords": [
14 | "fis",
15 | "postpackager",
16 | "package",
17 | "simple"
18 | ],
19 | "author": "hefangshi",
20 | "license": "MIT",
21 | "dependencies": {
22 | "stable": "0.1.5"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | Copyright (C) 2013 baidu.com
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is furnished
8 | to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in
11 | all copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
14 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
15 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
16 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
17 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
18 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
19 | DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # fis-postpackager-simple
2 |
3 | 用于自动打包页面零散资源和应用打包资源的[FIS](https://github.com/fex-team/fis/)插件
4 |
5 | ## 功能
6 |
7 | - 自动将页面中声明的资源引用替换为pack中设置的资源
8 | - 自动将未打包的零散资源按照引用顺序打包,默认关闭
9 |
10 | ## 用法
11 |
12 | $ npm install -g fis-postpackager-simple
13 | $ vi path/to/project/fis-conf.js #编辑项目配置文件
14 |
15 | ```javascript
16 | //file : path/to/project/fis-conf.js
17 | //使用simple插件,自动应用pack的资源引用
18 | fis.config.set('modules.postpackager', 'simple');
19 | //开始autoCombine可以将零散资源进行自动打包
20 | fis.config.set('settings.postpackager.simple.autoCombine', true);
21 | //开启autoReflow使得在关闭autoCombine的情况下,依然会优化脚本与样式资源引用位置
22 | fis.config.set('settings.postpackager.simple.autoReflow', true);
23 | ```
24 |
25 | ## 自动打包处理策略
26 |
27 | 开启了autoCombine后,为了保证资源引用顺序的正确,插件会自动调整脚本的加载位置
28 |
29 | - `````` 引用的脚本默认会在打包后移动到body底部
30 | - `````` 引用或声明的脚本会移动到head底部 **仅限pack打包,自动打包不适用**
31 | - `````` 引用或声明的脚本和样式不会进行自动打包
32 | - `````` 引用的样式表默认会在打包后移动到head底部
33 | - `````` 编写的内嵌脚本将会移动到body底部
34 | - ``` 资源
47 | * 获取html页面中的 资源
48 | * 由于已经在标准流程之后,无需处理inline
49 | * 不需要改动页面中内嵌的样式
50 | * 需要将页面中内嵌的脚本移动到所有脚本的最下方
51 | * 需要去除注释内的引用
52 | * @param content
53 | * @param pathMap
54 | * @param usePlaceholder
55 | */
56 | function analyzeHtml(content, pathMap, usePlaceholder) {
57 | var reg =
58 | /(\n';
392 | if (js.head) {
393 | headScripts += script;
394 | }
395 | else {
396 | scripts += script;
397 | }
398 | });
399 | content = modBodyContent(content, scripts, settings);
400 | content = modHeadContent(content, headScripts, settings);
401 | return content;
402 | }
403 |
404 | function injectCss(cssList, content, ret, settings) {
405 | var styles = '';
406 | cssList.forEach(function (css) {
407 | var uri;
408 | if (css.type === 'pkg') {
409 | uri = ret.map.pkg[css.id].uri;
410 | }
411 | else {
412 | uri = ret.map.res[css.id].uri;
413 | }
414 | styles += '\n';
415 | });
416 | content = modHeadContent(content, styles, settings);
417 | return content;
418 | }
419 |
420 | function injectInlineJs(inlineScripts, content, ret, settings) {
421 | var inlines = '',
422 | headInlines = '';
423 | inlineScripts.forEach(function (script) {
424 | if (script.head) {
425 | headInlines += script.content;
426 | }
427 | else {
428 | inlines += script.content;
429 | }
430 | });
431 | content = modBodyContent(content, inlines, settings);
432 | content = modHeadContent(content, headInlines, settings);
433 | return content;
434 | }
435 |
436 | function modHeadContent(content, mod, settings) {
437 | if (settings.headTag.test(content)) {
438 | content = content.replace(settings.headTag, mod + '$&');
439 | }
440 | else if (settings.forceOutput) {
441 | content = mod + content;
442 | }
443 | return content;
444 | }
445 |
446 | function modBodyContent(content, mod, settings) {
447 | if (settings.bodyTag.test(content)) {
448 | content = content.replace(settings.bodyTag, mod + '$&');
449 | }
450 | else if (settings.forceOutput) {
451 | content += mod;
452 | }
453 | return content;
454 | }
455 |
456 | function injectJsWithPlaceHolder(jsList, content, ret) {
457 | jsList.forEach(function (js) {
458 | var uri, id, file;
459 | if (js.type === 'pkg') {
460 | uri = ret.map.pkg[js.id].uri;
461 | file = ret.packMap.packToFile[js.id];
462 | id = js.srcId;
463 | }
464 | else {
465 | uri = ret.map.res[js.id].uri;
466 | file = ret.src[js.id];
467 | id = js.id;
468 | }
469 | var script = '\n';
471 | content = content.replace(placeHolders[id], script);
472 | placeHolders[id] = false;
473 | });
474 | return content;
475 | }
476 |
477 | function injectCssWithPlaceHolder(cssList, content, ret) {
478 | cssList.forEach(function (css) {
479 | var uri, id;
480 | if (css.type === 'pkg') {
481 | uri = ret.map.pkg[css.id].uri;
482 | id = css.srcId;
483 | }
484 | else {
485 | uri = ret.map.res[css.id].uri;
486 | id = css.id;
487 | }
488 | var style = '\n';
489 | content = content.replace(placeHolders[id], style);
490 | placeHolders[id] = false;
491 | });
492 | return content;
493 | }
494 |
495 | function cleanPlaceHolder(content) {
496 | fis.util.map(placeHolders, function (id, placeholder) {
497 | if (placeholder) {
498 | content = content.replace(placeholder, '');
499 | }
500 | placeHolders[id] = false;
501 | });
502 | return content;
503 | }
504 |
505 |
506 | module.exports = function (ret, conf, settings, opt) { //打包后处理
507 | if (!opt.pack) {
508 | return;
509 | }
510 | combineCache = {};
511 | combineCount = 0;
512 | settings = fis.util.merge(fis.util.clone(defaultSetting), settings);
513 | settings.headTag = wrapTag(settings.headTag);
514 | settings.bodyTag = wrapTag(settings.bodyTag);
515 | var pathMap = getResourcePathMap(ret, conf, settings, opt);
516 | ret.packMap = getPackMap(ret, conf, settings, opt);
517 | // autoCombine模式下,autoReflow必为真
518 | if (settings.autoCombine) {
519 | settings.autoReflow = true;
520 | }
521 | fis.util.map(ret.src, function (subpath, file) {
522 | if (file.useCompile && file.isHtmlLike && file.noMapJs !== false) { // 类html文件
523 | placeHolders = {};
524 | var content = file.getContent();
525 | var result = analyzeHtml(content, pathMap, !settings.autoReflow);
526 | content = result.content;
527 | var jsList = getPkgResource(result.resources.scripts, ret, settings.fullPackHit.js);
528 | var cssList = getPkgResource(result.resources.styles, ret, settings.fullPackHit.css);
529 | if (settings.autoCombine) {
530 | jsList = autoCombine(jsList, ret, conf, settings, opt);
531 | cssList = autoCombine(cssList, ret, conf, settings, opt);
532 | }
533 | if (settings.autoReflow) {
534 | content = injectJs(jsList, content, ret, settings);
535 | content = injectCss(cssList, content, ret, settings);
536 | content = injectInlineJs(result.resources.inlineScripts, content, ret, settings);
537 | }
538 | else {
539 | content = injectJsWithPlaceHolder(jsList, content, ret);
540 | content = injectCssWithPlaceHolder(cssList, content, ret);
541 | content = cleanPlaceHolder(content);
542 | }
543 | file.setContent(content);
544 | if (file.useCache) {
545 | ret.pkg[file.subpath] = file;
546 | }
547 | }
548 | });
549 | };
550 |
--------------------------------------------------------------------------------