cgreact-loader
Version:
CGReact与Webpack配套的loader
267 lines (266 loc) • 14 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var FS = require("fs");
var path = require("path");
var chalk = require("chalk");
var figlet = require("figlet");
var JSSCli = require("jss-cli");
var SassLoader = require("sass-loader");
var CssLoader = require("css-loader");
var ExtractLoader = require("extract-loader");
var FileLoader = require("file-loader");
var TSLoader = require("ts-loader");
var cgreact_transformer_1 = require("./cgreact-transformer");
console.log(chalk.yellow(figlet.textSync('CGReact-Loader', { horizontalLayout: 'full', })) + chalk.red("V" + require("../package.json").version)); // 打印CGReact-Loader的版本信息
module.exports.raw = true; //使用RawLoader这样png图片才能正确处理
function CGReactLoader(content, map, mainTemplate) {
/*这种方式可以捕捉到编译结束的事件,但是需要在webpack的entry配置中增加一个? ,但显然不是最优的方案*/
// if (!this._module.issuer)
// {
// this.async();
// return this.loadModule(this.resource.replace("?", ""), (error, result, sourecMap, moudule) =>
// {
// this.callback(error, result, sourecMap);
// console.log(chalk.blue("CGReactLoader干完了!"));
// });
// }
// 根据不同的文件类型进行处理
switch (path.extname(this.resource.split("?")[0]).toLocaleLowerCase()) {
case ".js":
{
if (/node_modules[/|\\]/.test(this.resource)) {
//对于node_modules中的模块加载js直接返回
return content;
}
else if (/assets[/|\\]js/.test(this.resource)) {
// 项目assets文件夹中的js目录中的内容作为file处理
return handleFile.call(prepareContext(this), content, map, mainTemplate);
}
else {
// 项目非assets文件夹中的JS仍作为JS模块来处理,但是要打印
console.log(chalk.blue("CGReactLoader处理了" + chalk.red("JSM") + " : ") + chalk.cyan(this.resource));
return content;
}
}
case ".ts":
case ".tsx":
case ".tsx?":
{
return handleTsx.call(prepareContext(this), content, map, mainTemplate);
}
case ".css":
{
if (/CGReactCore|CGReactLayui|CGReactAntd[/|\\]/.test(this.resource)) {
// 组件库中的css文件夹作为scss来处理,这样把样式打包在代码中不会有额外文件产生
return handleSass.call(prepareContext(this), content, map, mainTemplate);
}
else if (/assets[/|\\]css/.test(this.resource) || /node_modules[/|\\]/.test(this.resource)) {
// 资产文件中或者node_module文件夹中的的css使用file来处理,它们可能是很诡异的,正常loader处理不了的
return handleFile.call(prepareContext(this), content, map, mainTemplate);
}
else {
// 其余情况产生可以引入的css文件,会调动extralLoader来处理css中的引入
return handleCss.call(prepareContext(this), content, map, mainTemplate);
}
}
case ".scss":
{
return handleSass.call(prepareContext(this), content, map, mainTemplate);
}
case ".png":
case ".svg":
case ".jpg":
case ".gif":
case ".wav":
case ".mp3":
case ".html":
{
return handleFile.call(prepareContext(this), content, map, mainTemplate);
}
case ".self":
{
return handleMdoule_deprecated.call(prepareContext(this), content, map, mainTemplate);
}
case ".woff":
case ".woff2":
case ".ttf":
{
return handleFile.call(prepareContext(this), content, map, mainTemplate);
}
default:
{
return handleUnknown.call(prepareContext(this), content, map, mainTemplate);
}
}
}
exports.default = CGReactLoader;
;
function prepareContext(context) {
var result = {};
for (var key in context) {
result[key] = context[key];
}
result.query = {};
return result;
}
function prepareSource(source) {
// 针对TS文件的import进行处理,将webpack注释转移到;号之前
var importArray = source.match(/;\s*\/\*webpackChunkName:.*\*\//g);
importArray && importArray.forEach(function (current) {
var replace = current.substring(1) + ";";
source = source.replace(current, replace);
});
return source;
}
function handleTsx(content, map, mainTemplate) {
console.log(chalk.blue("CGReactLoader处理了" + chalk.red("TSX") + " : ") + chalk.green(this.resource));
// Buffer转为字符串才能正确处理
content = content.toString();
// 进行TS的预编译处理,处理webpackChunkName的自动转换
content = prepareSource(content);
// if (path.basename(this.resource) == "main.tsx")
// {
// console.log("-------------编译前-------------------");
// console.log(content);
// let testContent= TS.transpileModule(content, {
// compilerOptions: {
// target: TS.ScriptTarget.ESNext,
// module: TS.ModuleKind.ESNext,
// jsx: TS.JsxEmit.Preserve
// },
// transformers: {before: [transformTypeScript]}
// }).outputText;
// console.log("-------------编译后-------------------");
// console.log(testContent);
// }
/* 开始按照配置进行ts的编译,
sourceMap必须配置为true,否则Webpack配置生成的source是ES5的像狗啃一样
注意module是管import的配置为esnext才能进行splitchunk
另外target必须ES6以上,否则transWebpackImportChunk会报错,notransfromFlag*/
this.query.compilerOptions = {
sourceMap: true,
module: "esnext",
target: "esnext",
jsx: "react"
};
this.query.getCustomTransformers = function () { return ({ before: [cgreact_transformer_1.default] }); };
this.query.transpileOnly = true; // 配这个会忽略TS的编译泛型检查
return TSLoader.call(this, content, map, mainTemplate);
}
function handleJSS(content, map, mainTemplate) {
var _this = this;
console.log(chalk.blue("CGReactLoader处理了" + chalk.red("JSS") + " : ") + chalk.cyan(this.resource));
// Buffer转为字符串才能正确处理
content = content.toString();
/** 偷梁换柱异步Loader的callback方法*/
var callback = this.async(); //先保存一下原来的接口作为我们的出口
var sassLoaderCallBack = function (error, cssContent, map, mainTemplate) {
// SASSLoader执行完后会调用这里的此时已经拿到标准的CSS
_this.async = function () { return cssLoaderCallBack; };
// 清理参数继续调用其他的laoder
Object.keys(_this.query).map(function (key) { return delete _this.query[key]; });
// 继续交给CSSLoader来处理其中通过url引入的文件资源
CssLoader.call(_this, cssContent, map, mainTemplate);
};
var cssLoaderCallBack = function (error, cssLoaderContent, map, mainTemplate) {
// 继续交给ExtractLoader处理CSS中以url方式引入的文件
_this.async = function () { return extractLoaderCallBack; };
ExtractLoader.call(_this, cssLoaderContent, map, mainTemplate);
};
var extractLoaderCallBack = function (error, extractLoaderContent, map, mainTemplate) {
// 利用JSS-CLI的函数转换css为jss
var jss = JSSCli.cssToJss({ code: extractLoaderContent });
// 需要返回JSS的代码,JSONStringify就可以了
var jssContent = "export default " + JSON.stringify(jss["@global"]);
//调用我们之前保存的真实的回调接口送结果
callback(error, jssContent, map, mainTemplate);
};
/** 开始按照逻辑处理CSS,按照SassLoader,CSSLoader,ExtractLoader,JSSLoader的顺序*/
this.async = function () { return sassLoaderCallBack; }; //偷梁换柱原来的异步接口
this.query.sassOptions = { outputStyle: "compressed" }; // 去除sass-loader编译css中的注释
SassLoader.call(this, content, map, mainTemplate);
}
function handleCss(content, map, mainTemplate) {
var _this = this;
console.log(chalk.blue("CGReactLoader处理了" + chalk.red("CSS") + " : ") + chalk.cyan(this.resource));
// Buffer转为字符串才能正确处理
content = content.toString();
/** 偷梁换柱异步Loader的callback方法*/
var callback = this.async(); //先保存一下原来的接口作为我们的出口
var sassLoaderCallBack = function (error, cssContent, map, mainTemplate) {
// 清理参数继续调用其他的laoder
Object.keys(_this.query).map(function (key) { return delete _this.query[key]; });
// 继续交给CSSLoader将样式抓好为标准module
_this.async = function () { return cssLoaderCallBack; };
CssLoader.call(_this, cssContent, map, mainTemplate);
};
var cssLoaderCallBack = function (error, cssLoaderContent, map, mainTemplate) {
// 继续交给ExtractLoader处理CSS中以url方式引入的文件
_this.async = function () { return extractLoaderCallBack; };
ExtractLoader.call(_this, cssLoaderContent, map, mainTemplate);
};
var extractLoaderCallBack = function (error, extractLoaderContent, map, mainTemplate) {
// 继续交给FileLoader作为文件打包,此时CSS中引入的文件路径已经修改为webpack编译后的正确路径
Object.keys(_this.query).map(function (key) { return delete _this.query[key]; }); // 清理参数继续调用其他的laoder
_this.query.name = '[path][name].[ext]';
_this.query.context = "./src/web";
var fileContent = FileLoader.call(_this, content, map, mainTemplate);
//调用我们之前保存的真实的回调接口送结果
callback(error, fileContent, map, mainTemplate);
};
/** 开始按照逻辑处理CSS,按照SassLoader,CSSLoader,FileLoader的顺序*/
this.async = function () { return sassLoaderCallBack; }; //偷梁换柱原来的异步接口
this.query.sassOptions = { outputStyle: "compressed" }; // 去除sass-loader编译css中的注释
SassLoader.call(this, content, map, mainTemplate);
}
function handleSass(content, map, mainTemplate) {
var _this = this;
console.log(chalk.blue("CGReactLoader处理了" + chalk.red("SCSS") + " : ") + chalk.cyan(this.resource));
// Buffer转为字符串才能正确处理
content = content.toString();
/** 偷梁换柱异步Loader的callback方法*/
var callback = this.async(); //先保存一下原来的接口作为我们的出口
var sassLoaderCallBack = function (error, cssContent, map, mainTemplate) {
// 清理参数继续调用其他的laoder
Object.keys(_this.query).map(function (key) { return delete _this.query[key]; });
// 继续交给CSSLoader将样式抓好为标准module
_this.async = function () { return cssLoaderCallBack; };
CssLoader.call(_this, cssContent, map, mainTemplate);
};
var cssLoaderCallBack = function (error, cssLoaderContent, map, mainTemplate) {
// 继续交给ExtractLoader处理CSS中以url方式引入的文件
_this.async = function () { return extractLoaderCallBack; };
ExtractLoader.call(_this, cssLoaderContent, map, mainTemplate);
};
var extractLoaderCallBack = function (error, extractLoaderContent, map, mainTemplate) {
//调用我们之前保存的真实的回调接口送结果
var fileContent = "module.exports='" + extractLoaderContent + "'";
callback(error, fileContent, map, mainTemplate);
};
/** 开始按照逻辑处理CSS,按照SassLoader,CSSLoader,FileLoader的顺序*/
this.async = function () { return sassLoaderCallBack; }; //偷梁换柱原来的异步接口
this.query.sassOptions = { outputStyle: "compressed" }; // 去除sass-loader编译css中的注释
SassLoader.call(this, content, map, mainTemplate);
}
function handleFile(content, map, mainTemplate) {
console.log(chalk.blue("CGReactLoader处理了" + chalk.red("File") + " : ") + chalk.cyan(this.resource));
// 利用file-laoder进行处理
this.query.name = '[path][name].[ext]';
this.query.context = "./src/web";
return FileLoader.call(this, content, map, mainTemplate);
}
function handleUnknown(content, map, mainTemplate) {
console.log(chalk.blue("CGReactLoader不知道怎么处理就处理为" + chalk.red("File") + " : ") + chalk.cyan(this.resource));
// 利用file-laoder进行处理
this.query.name = '[path][name].[ext]';
this.query.context = "./src/web";
return FileLoader.call(this, content, map, mainTemplate);
}
function handleMdoule_deprecated(content, map, mainTemplate) {
console.log(chalk.blue("CGReactLoader处理了" + chalk.red("Self") + " : ") + chalk.cyan(this.resource));
var scriptModule = this.query.module ? FS.readFileSync(this.query.module, "utf-8") : undefined;
// 确保esModule的导出方式不会read-only错误
content = content.replace("export default", "const cg_exports=");
content = content.replace("module.exports", "const cg_exports");
return content + scriptModule;
}