UNPKG

cgreact-loader

Version:

CGReact与Webpack配套的loader

267 lines (266 loc) 14 kB
"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; }