builder-webpack4
Version:
819 lines (818 loc) • 33.9 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
/**
* Copyright (c) 2018 Tencent Inc.
*
* Webpack构建器,适用于NOW直播IVWEB团队工程项目.
*
* cpselvis <cpselvis@gmal.com>
*/
var path_1 = __importDefault(require("path"));
var glob_1 = __importDefault(require("glob"));
var webpack_1 = __importDefault(require("webpack"));
var fs_1 = __importDefault(require("fs"));
var osenv_1 = __importDefault(require("osenv"));
var html_webpack_plugin_1 = __importDefault(require("html-webpack-plugin"));
var mini_css_extract_plugin_1 = __importDefault(require("mini-css-extract-plugin"));
var html_webpack_externals_plugin_1 = __importDefault(require("html-webpack-externals-plugin"));
var webpack_subresource_integrity_1 = __importDefault(require("webpack-subresource-integrity"));
var offline_webpack_plugin_1 = __importDefault(require("offline-webpack-plugin"));
var clean_webpack_plugin_1 = __importDefault(require("clean-webpack-plugin"));
var string_replace_webpack_plugin_1 = __importDefault(require("string-replace-webpack-plugin"));
var html_inline_css_webpack_plugin_1 = __importDefault(require("html-inline-css-webpack-plugin"));
var optimize_css_assets_webpack_plugin_1 = __importDefault(require("optimize-css-assets-webpack-plugin"));
var util_1 = require("./util");
var config_1 = __importDefault(require("./config"));
// 当前运行的时候的根目录
var projectRoot = config_1.default.getPath('feflow.json');
if (!projectRoot) {
projectRoot = config_1.default.getPath('feflow.js');
}
;
// 最基础的配置
var baseConfig = {
target: 'web',
cache: true,
entry: glob_1.default.sync(path_1.default.join(projectRoot, './src/pages/*')),
module: {
rules: []
},
output: '',
plugins: [],
resolve: {
alias: glob_1.default.sync(path_1.default.join(projectRoot, './src/*/')) // 支持Webpack import绝对路径的写法
},
resolveLoader: {},
// 对体积过大的包进行提示
performance: {
hints: 'warning',
maxAssetSize: 200000,
maxEntrypointSize: 400000,
assetFilter: function (assetFilename) {
// Function predicate that provides asset filenames
return assetFilename.endsWith('.css') || assetFilename.endsWith('.js');
}
}
};
var PATHS = {
src: path_1.default.join(projectRoot, 'src')
};
var Builder = /** @class */ (function () {
function Builder() {
}
/**
* @function createDevConfig
* @desc 创建用于开发过程中的webpack打包配置
*
* @param {Object} options 参数
* @param {Boolean} options.usePx2rem 是否启用px2rem
* @param {Number} options.remUnit px2rem的单位, 默认75
* @param {Number} options.remPrecision px2rem的精度,默认8
* @param {Number} options.port webpack打包的端口号,默认8001
* @param {String} options.inject 是否注入chunks
* @param {Boolean} options.inlineCSS 是否注入inline打包出来的css
* @param {String} options.babelrcPath 指定babelrc配置路径
*
* @example
*/
Builder.createDevConfig = function (options) {
var devConfig = util_1.deepCopy(baseConfig);
devConfig.mode = 'development';
// 设置打包规则
var devRules = [];
// 设置HTML解析规则
devRules.push(this.setHtmlRule());
// 设置图片解析规则
devRules.push(this.setImgRule(false));
// 设置CSS解析规则
devRules.push(this.setCssRule());
// 设置使用CSS Modules的CSS解析规则
devRules.push(this.setCssModulesRule());
// 设置Less解析规则,开发环境开启css-hot-loader
devRules.push(this.setLessRule(true, options.usePx2rem, options.remUnit, options.remPrecision));
// 设置使用CSS Modules的Less解析规则,开发环境开启css-hot-loader
devRules.push(this.setLessModulesRule(true, options.usePx2rem, options.remUnit, options.remPrecision));
// 设置JS解析规则
devRules.push(this.setJsRule(options.babelrcPath, options.babelrc));
// 设置TS解析规则
devRules.push(this.setTsRule());
// 设置字体解析规则
devRules.push(this.setFontRule());
// 启用端对端测试的特殊模式
if (options.enableE2ETest) {
devRules.push(this.setE2ETestRule());
devConfig.devtool = 'sourcemap';
}
else {
devConfig.devtool = 'inline-source-map';
}
// 设置打包插件
var devPlugins = [];
devPlugins.push(new string_replace_webpack_plugin_1.default());
// 设置提取CSS为一个单独的文件的插件
devPlugins.push(this.setMiniCssExtractPlugin(false, ''));
if (options.useReact !== false) {
// React, react-dom 通过cdn引入
devPlugins.push(this.setExternalPlugin(options.externals));
}
// 增加热更新组件
devPlugins.push(new webpack_1.default.HotModuleReplacementPlugin());
// 抽离公共js
// devPlugins.push(this.setCommonsChunkPlugin());
// 多页面打包
// 开发环境不使用inlineCss,保证css热更新功能
var _a = this.setMultiplePage(devConfig.entry, false, options.inject, false, '', ''), newEntry = _a.newEntry, htmlWebpackPlugins = _a.htmlWebpackPlugins, cssInlinePlugins = _a.cssInlinePlugins;
devPlugins = devPlugins.concat(htmlWebpackPlugins, cssInlinePlugins);
devConfig.entry = newEntry;
// 开发阶段增加sourcemap.
// 这里还是依然按照原来的配置,将静态资源用根目录伺服
devConfig.output = this.setOutput(false, '', '/', options.outDir);
devConfig.module.rules = devRules;
devConfig.plugins = devPlugins;
devConfig.devServer = this.setDevServer(options.port || 8001);
devConfig.resolve.alias = this.setAlias(options.alias);
devConfig.resolve.extensions = ['.js', '.jsx', '.ts', '.tsx', '.json'];
// 设置 loader 的npm包查找的相对路径,包括本地node_modules、.feflow、测试环境的node_module
devConfig.resolveLoader = this.setResolveLoaderPath(options.runtime);
return devConfig;
};
/**
* @function createProdConfig
* @desc 创建用于生产环境中的webpack打包配置
*
* @param {Object} options 参数
* @param {Boolean} options.minifyHTML 是否压缩HTML
* @param {Boolean} options.minifyCSS 是否压缩CSS
* @param {Boolean} options.minifyJS 是否压缩JS
* @param {Boolean} options.usePx2rem 是否启用px2rem
* @param {Number} options.remUnit px2rem的单位, 默认75
* @param {Number} options.remPrecision px2rem的精度,默认8
* @param {String} options.moduleName 模块名称 (如果不传,则放在根目录)
* @param {String} options.bizName 业务名称
* @param {String} options.inject 是否注入chunks
* @param {Boolean} options.inlineCSS 是否注入inline打包出来的css
* @param {String} options.babelrcPath 指定babelrc配置路径
* @example
*/
Builder.createProdConfig = function (options) {
var prodConfig = util_1.deepCopy(baseConfig);
prodConfig.mode = 'production';
var bizName = options.bizName;
var moduleName = options.moduleName;
// 业务域名
var domain = options.domain || 'now.qq.com';
var cdn = options.cdn || '11.url.cn';
var product = options.product || 'now';
// Html 路径前缀, 打包时的目录
var htmlPrefix = moduleName ? "../../webserver/" + bizName : '../webserver';
// Css, Js, Img等静态资源路径前缀, 打包时的目录
var assetsPrefix = moduleName ? "cdn/" + bizName : 'cdn';
var cdnUrl = moduleName ? "//" + cdn + "/" + product + "/" + moduleName + "/" + bizName : "//" + cdn + "/" + product + "/" + bizName;
var serverUrl = moduleName ? "//" + domain + "/" + moduleName + "/" + bizName : "//" + domain + "/" + bizName;
// const regex = new RegExp(assetsPrefix + '/', 'g');
// 设置打包规则
var prodRules = [];
// 设置HTML解析规则
prodRules.push(this.setHtmlRule());
// 设置图片解析规则, 图片需要hash
prodRules.push(this.setImgRule(true, ''));
// 设置CSS解析规则
prodRules.push(this.setCssRule());
// 设置开启CSS Modules的CSS解析规则
prodRules.push(this.setCssModulesRule());
// 设置Less解析规则,生产环境不开启css-hot-loader
prodRules.push(this.setLessRule(false, options.usePx2rem, options.remUnit, options.remPrecision));
// 设置开启CSS Modules的Less解析规则,生产环境不开启css-hot-loader
prodRules.push(this.setLessModulesRule(false, options.usePx2rem, options.remUnit, options.remPrecision));
// 设置JS解析规则
prodRules.push(this.setJsRule(options.babelrcPath, options.babelrc));
// 设置TS解析规则
prodRules.push(this.setTsRule());
// 设置字体解析规则
prodRules.push(this.setFontRule());
// 启用端对端测试的特殊模式
if (options.enableE2ETest) {
prodRules.push(this.setE2ETestRule());
prodConfig.devtool = 'sourcemap';
}
// 设置打包插件
var prodPlugins = [];
// 清空Public目录插件, https://github.com/johnagan/clean-webpack-plugin/issues/17
prodPlugins.push(new clean_webpack_plugin_1.default([options.outDir], {
root: projectRoot,
verbose: true,
dry: false
}));
prodPlugins.push(new string_replace_webpack_plugin_1.default());
// 设置提取CSS为一个单独的文件的插件
prodPlugins.push(this.setMiniCssExtractPlugin(true, ''));
prodPlugins.push(this.setOptimizeCssAssetsPlugin());
if (options.minifyJS) {
// 压缩JS
// webpack4 mode=production 下会默认启动 terser-webpack-plugin
}
if (options.useReact !== false) {
// React, react-dom 通过cdn引入
prodPlugins.push(this.setExternalPlugin(options.externals));
}
// 抽离公共js
/**
* 这个地方应当支持配置
*/
//prodPlugins.push(this.setCommonsChunkPlugin());
// 支持Fis3的 inline 语法糖 多页面打包, 默认压缩html
var _a = this.setMultiplePage(prodConfig.entry, options.minifyHTML, options.inject, options.inlineCSS, assetsPrefix, htmlPrefix), newEntry = _a.newEntry, htmlWebpackPlugins = _a.htmlWebpackPlugins, cssInlinePlugins = _a.cssInlinePlugins;
prodPlugins = prodPlugins.concat(htmlWebpackPlugins, cssInlinePlugins);
if (options.useSri !== false) {
// 给生成出来的js bundle增加跨域头(cross-origin),便于错误日志记录
prodPlugins.push(this.setSriPlugin());
}
prodPlugins.push(this.setOffline(assetsPrefix, htmlPrefix, cdnUrl, serverUrl, domain, cdn, product, options.outDir));
prodConfig.entry = newEntry;
prodConfig.output = this.setOutput(true, assetsPrefix, cdnUrl + '/', options.outDir);
prodConfig.module.rules = prodRules;
prodConfig.plugins = prodPlugins;
prodConfig.bail = true;
prodConfig.resolve.alias = this.setAlias(options.alias);
prodConfig.resolve.extensions = ['.js', '.jsx', '.ts', '.tsx', '.json'];
// 设置 loader 的npm包查找的相对路径,此处设置在全局的 .feflow 目录下
prodConfig.resolveLoader = this.setResolveLoaderPath(options.runtime);
return prodConfig;
};
/**
* 设置打包后的输出 output 内容
* @param useHash 是否开启JS资源hash
* @param pathPrefix JS的前缀, 不传入则为空
* @param publicPath
* @returns {{filename: string, path: string, publicPath: *}}
* @private
*/
Builder.setOutput = function (useHash, pathPrefix, publicPath, outDir) {
var hash = '';
outDir = outDir || 'public';
if (useHash) {
hash = '_[chunkhash:8]';
}
return {
filename: "[name]" + hash + ".js?_bid=152",
path: path_1.default.join(projectRoot, outDir + "/" + pathPrefix),
publicPath: publicPath,
crossOriginLoading: 'anonymous'
};
};
/**
* 设置图片解析规则
* @param useHash 是否开启图片资源hash
* @param pathPrefix 图片的前缀,不传入则为空
* @returns {{test: RegExp, use: {loader: string, options: {name: string}}}}
* @private
*/
Builder.setImgRule = function (useHash, pathPrefix) {
var filename = '';
var hash = '';
if (pathPrefix) {
filename = pathPrefix + '/';
}
if (useHash) {
hash = '_[hash:8]';
}
return {
test: /\.(png|svg|jpg|gif|blob)$/,
use: {
loader: 'inline-file-loader',
options: {
name: filename + "img/[name]" + hash + ".[ext]"
}
}
};
};
/**
* 设置字体解析规则
*/
Builder.setFontRule = function () {
return {
test: /\.(woff|woff2|eot|ttf|otf)$/,
use: {
loader: 'file-loader'
}
};
};
/**
* 设置 Html 文件解析规则
* 支持 Fis3 的 ?inline 语法糖
*
* @returns {{test: RegExp, use: Array}}
* @private
*/
Builder.setHtmlRule = function () {
var htmlRuleArray = [];
htmlRuleArray.push({
loader: 'html-loader',
options: {
// 支持 html `${}` 语法
interpolate: 1,
attrs: [':src']
}
});
// Fis3 inline 语法糖支持
htmlRuleArray.push({
loader: 'replace-text-loader',
options: {
rules: [
{
// inline script, 匹配所有的<script src="package?__inline"></script> 需要inline的标签
// 并且替换为
// <script>${require('raw-loader!babel-loader!../../node_modules/@tencent/report
// - whitelist')}</script> 语法
pattern: /<script.*?src="(.*?)\?__inline".*?>.*?<\/script>/gmi,
replacement: function (source) {
// 找到需要 inline 的包
var result = /<script.*?src="(.*?)\?__inline"/gmi.exec(source);
var pkg = result && result[1];
return "<script>${require('raw-loader!babel-loader!" + pkg + "')}</script>";
}
}, {
// inline html, 匹配<!--inline[/assets/inline/meta.html]-->语法
pattern: /<!--inline\[.*?\]-->/gmi,
replacement: function (source) {
// 找到需要 inline 的包
var result = /<!--inline\[(.*?)\]-->/gmi.exec(source);
var path = result && result[1];
if (path && path[0] === '/') {
path = '../..' + path;
}
return "${require('raw-loader!" + path + "')}";
}
}
]
}
});
return { test: /index\.html$/, use: htmlRuleArray };
};
/**
* 设置CSS解析规则
*/
Builder.setCssRule = function () {
return {
test: Builder.cssRegex,
exclude: Builder.cssModulesRegex,
use: ['style-loader', 'css-loader']
};
};
/**
* 设置使用CSS Modules的CSS解析规则
*/
Builder.setCssModulesRule = function () {
return {
test: Builder.cssModulesRegex,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
modules: true,
getLocalIdent: util_1.getCSSModulesLocalIdent
}
}
]
};
};
/**
* 设置Less文件解析规则
*
* @param useHotLoader 是否使用css-hot-loader
* @param usePx2rem 是否使用px2rem loader
* @param remUnit rem单位,默认75
* @param remPrecision rem精度, 默认8
* @returns {{test: RegExp, use: *}}
* @private
*/
Builder.setLessRule = function (useHotLoader, usePx2rem, remUnit, remPrecision) {
var cssRuleArray = [];
if (useHotLoader) {
cssRuleArray.push({
loader: 'css-hot-loader',
options: {}
});
}
cssRuleArray.push({
loader: mini_css_extract_plugin_1.default.loader,
options: {}
});
// 加载Css loader, 判断是否开启压缩
var cssLoaderRule = {
loader: "css-loader",
options: {}
};
cssRuleArray.push(cssLoaderRule);
// 如果开启px2rem,则加载px2rem-loader
if (usePx2rem) {
cssRuleArray.push({
loader: "px2rem-loader",
options: {
remUnit: remUnit || 75,
remPrecision: remPrecision || 8
}
});
}
// css 前缀,兼容低版本浏览器
cssRuleArray.push({
loader: 'postcss-loader',
options: {
plugins: function () { return [
require('autoprefixer')({
overrideBrowserslist: ["last 2 version", "> 1%", "iOS 7"]
})
]; }
}
});
// 雪碧图loader
cssRuleArray.push({
loader: "sprites-loader",
options: {}
});
// 加载解析less的less-loader
cssRuleArray.push({
loader: "less-loader",
options: {
includePaths: [path_1.default.join(projectRoot, "./src")]
}
});
return {
test: Builder.lessRegex,
exclude: Builder.lessModulesRegex,
use: cssRuleArray
};
};
/**
* 设置使用CSS Modules的Less文件解析规则
*
* @param useHotLoader 是否使用css-hot-loader
* @param usePx2rem 是否使用px2rem loader
* @param remUnit rem单位,默认75
* @param remPrecision rem精度, 默认8
* @returns {{test: RegExp, use: *}}
* @private
*/
Builder.setLessModulesRule = function (useHotLoader, usePx2rem, remUnit, remPrecision) {
var cssRuleArray = [];
if (useHotLoader) {
cssRuleArray.push({
loader: 'css-hot-loader',
options: {}
});
}
cssRuleArray.push({
loader: mini_css_extract_plugin_1.default.loader,
options: {}
});
// 加载Css loader, 开启Css Modules
var cssLoaderRule = {
loader: "css-loader",
options: {
modules: true,
getLocalIdent: util_1.getCSSModulesLocalIdent
}
};
cssRuleArray.push(cssLoaderRule);
// 如果开启px2rem,则加载px2rem-loader
if (usePx2rem) {
cssRuleArray.push({
loader: "px2rem-loader",
options: {
remUnit: remUnit || 75,
remPrecision: remPrecision || 8
}
});
}
// css 前缀,兼容低版本浏览器
cssRuleArray.push({
loader: 'postcss-loader',
options: {
plugins: function () { return [
require('autoprefixer')({
overrideBrowserslist: ["last 2 version", "> 1%", "iOS 7"]
})
]; }
}
});
// 雪碧图loader
cssRuleArray.push({
loader: "sprites-loader",
options: {}
});
// 加载解析less的less-loader
cssRuleArray.push({
loader: "less-loader",
options: {
includePaths: [path_1.default.join(projectRoot, "./src")]
}
});
return {
test: Builder.lessModulesRegex,
use: cssRuleArray
};
};
/**
* 设置Js文件解析规则, 此处使用happypack,多实例构建
* @param babelrc 是否搜索相关的babel类型的配置文件,并和现有的babel文件进行合并
* @returns {{test: RegExp, loader: string}}
* @private
*/
Builder.setJsRule = function (babelrcPath, babelrc) {
if (babelrc === void 0) { babelrc = true; }
return {
test: /\.jsx?$/,
include: path_1.default.join(projectRoot, 'src'),
use: [
{
loader: 'thread-loader',
options: {
workers: 3
}
},
{
loader: 'babel-loader',
options: {
// babel默认查找根目录下的babel.config.js作为全局配置,除非在此选项强制指定;
// 且此选项不会影响加载.babelrc,参考:https://babeljs.io/docs/en/options#configfile
configFile: babelrcPath && path_1.default.join(process.cwd(), babelrcPath),
// 是否搜索相关的babel类型的配置文件,并和现有的babel文件进行合并
babelrc: babelrc
}
}
]
};
};
/**
* 设置TS文件解析规则, 此处使用happypack,多实例构建
*
* @returns {{test: RegExp, loader: string}}
* @private
*/
Builder.setTsRule = function () {
return { test: /\.ts(x?)$/, loader: 'happypack/loader', exclude: path_1.default.join(projectRoot, 'node_modules') };
};
/**
* 设置提取Css资源的插件
* @param useHash 是否开启图片资源hash
* @param pathPrefix CSS的前缀,不传入则为空
* @private
*/
Builder.setMiniCssExtractPlugin = function (useHash, pathPrefix) {
var filename = '';
var hash = '';
if (pathPrefix) {
filename = pathPrefix + '/';
}
if (useHash) {
hash = '_[contenthash:8]';
}
return new mini_css_extract_plugin_1.default({
filename: filename + "[name]" + hash + ".css"
});
};
/**
* 设置端对端测试的一些规则
*
* @returns {Object}
* @private
*/
Builder.setE2ETestRule = function () {
return {
test: /\.js$/,
use: {
loader: 'istanbul-instrumenter-loader',
options: { esModules: true }
},
enforce: 'post',
exclude: /node_modules|.\spec\.js$/,
};
};
Builder.setOptimizeCssAssetsPlugin = function () {
return new optimize_css_assets_webpack_plugin_1.default({
assetNameRegExp: /\.css$/g,
cssProcessor: require('cssnano')
});
};
/**
* 不把React, react-dom打到公共包里,并在html插入cdn资源
* @private
*/
Builder.setExternalPlugin = function (externals) {
var newExternals = externals || [
{
module: 'react',
entry: '//11.url.cn/now/lib/16.2.0/react.min.js?_bid=3123',
global: 'React'
}, {
module: 'react-dom',
entry: '//11.url.cn/now/lib/16.2.0/react-dom.min.js?_bid=3123',
global: 'ReactDOM'
}
];
return new html_webpack_externals_plugin_1.default({ externals: newExternals });
};
/**
* 多页面打包
* @param entries glob的entry路径
* @param minifyHtml 是否压缩html
* @param inject 是否自动注入打包出来的js和css
* @param inlineCSS 是否inline打包出来的css
* @param assetsPrefix Css, Js, img的路径前缀
* @param htmlPrefix Html的路径前缀
* @returns {{newEntry: {}, htmlWebpackPlugins: Array}}
* @private
*/
Builder.setMultiplePage = function (entries, minifyHtml, inject, _inlineCSS, _assetsPrefix, htmlPrefix) {
var newEntry = {};
var htmlWebpackPlugins = [];
var cssInlinePlugins = [];
Object
.keys(entries)
.map(function (index) {
var entry = entries[index];
/**
* TODO: 这个地方会不会太强业务相关了?
*/
var entryFile = entry + "/init.js";
// 支持 init.js 文件不是必须存在的场景,纯html
var isEntryFileExists = fs_1.default.existsSync(entryFile);
var match = entry.match(/\/pages\/(.*)/);
var pageName = match && match[1];
var filename = '';
if (htmlPrefix) {
filename = htmlPrefix + '/';
}
if (isEntryFileExists) {
newEntry[pageName] = entryFile;
}
htmlWebpackPlugins.push(new html_webpack_plugin_1.default({
template: path_1.default.join(projectRoot, "src/pages/" + pageName + "/index.html"),
filename: "" + filename + pageName + ".html",
chunks: [pageName],
// assetsPrefix: `${assetsPrefix}/`,
inject: inject && isEntryFileExists,
minify: minifyHtml
? {
html5: true,
collapseWhitespace: true,
preserveLineBreaks: false,
minifyCSS: true,
minifyJS: true,
removeComments: false
}
: false
}));
// Inline 生成出来的css
if (_inlineCSS) {
var pageName_1 = path_1.default.normalize(entry).split(path_1.default.sep).pop();
if (pageName_1) {
cssInlinePlugins.push(new html_inline_css_webpack_plugin_1.default({
filter: function (fileName) {
var cssFileName = fileName;
if (/\.css$/.test(fileName)) {
// file的hash默认是8个,如果另外定义数量请注意修改这里的截取位置(MiniCssExtractPlugin中)
cssFileName = fileName.slice(0, fileName.length - 13);
}
return (pageName_1 === cssFileName) || new RegExp(pageName_1 + ".html$").test(fileName);
}
}));
}
}
});
return { newEntry: newEntry, htmlWebpackPlugins: htmlWebpackPlugins, cssInlinePlugins: cssInlinePlugins };
};
/**
* 给生成的 js bundle文件增加 SRI 资源校验,防止CDN劫持
* @returns {SriPlugin}
* @private
*/
Builder.setSriPlugin = function () {
return new webpack_subresource_integrity_1.default({
hashFuncNames: ['sha256', 'sha384']
});
};
/**
* 离线包打包逻辑
* @param assetsPrefix CSS、Img、JS等打包路径前缀
* @param htmlPrefix Html打包路径前缀
* @param cdnUrl CDN路径
* @param serverUrl now.qq.com路径
* @param domain 域名
* @param cdn cdn路径
* @param product cdn对应的产品
* @private
*/
Builder.setOffline = function (assetsPrefix, htmlPrefix, _cdnUrl, serverUrl, domain, cdn, product, outDir) {
outDir = outDir || 'public';
return new offline_webpack_plugin_1.default({
path: path_1.default.join(projectRoot, "./" + outDir + "/offline"),
filename: 'offline.zip',
pathMapper: function (assetPath) {
if (assetPath.indexOf(htmlPrefix) !== -1) {
// 所有资源都改成 now.qq.com 的域名, 防止跨域问题
assetPath = assetPath.replace(htmlPrefix, '');
}
else if (assetPath.indexOf(assetsPrefix) !== -1) {
assetPath = assetPath.replace(assetsPrefix, '');
}
return path_1.default.join(serverUrl.replace('//', ''), assetPath);
},
beforeAddBuffer: function (source, assetPath) {
if (assetPath.indexOf(htmlPrefix) !== -1) {
// 基础包域名修改, 防止跨域问题
source = source.replace(/\/\/11\.url\.cn\/now\/([^"'\)\`]+)(["'\`\)])/g, "//" + domain + "/$1$2");
// 业务资源的域名修改, 防止跨域问题
var regex = new RegExp("//" + cdn + "/" + product + "/([^\"')`]+)([\"'`)])", 'g');
source = source.replace(regex, "//" + domain + "/$1$2");
// 去掉 crossorigin="annoymous"
source = source.replace(/crossorigin=\"anonymous\"/g, '');
// 去掉 业务 js 文件的 ?_bid=152
source = source.replace(/\?_bid=152/g, '');
// 去掉业务 js 上的 integrity 属性
source = source.replace(/(<script.*)integrity=".*?"/g, '$1');
// 注入离线包的版本号. pack
var inject = {
version: Date.now()
};
source = source.replace(/(<script)/, '<script>var pack = ' + JSON.stringify(inject) + '</script>$1');
}
return source;
}
});
};
/**
* Code split, 提取出公共js文件,避免每个页面重复打包
*/
// static setCommonsChunkPlugin() {
// return new webpack.optimize.CommonsChunkPlugin({
// name: 'common'
// });
// }
/**
* 设置dev server,WDS配置
* @param port
* @returns {{contentBase: string, inline: boolean, historyApiFallback: boolean, disableHostCheck: boolean, port: *}}
* @private
*/
Builder.setDevServer = function (port) {
return {
contentBase: path_1.default.join(projectRoot, './src'),
inline: true,
historyApiFallback: false,
disableHostCheck: true,
port: port
};
};
/**
* 设置引用的Alias路径匹配规则,以src下面的目录为根目录
* TODO: 这个地方是否可以替代css绝对路径的问题
* 支持import TitleBar from "/modules/components/titlebar" 绝对路径语法
* @param alias 用户自定义的alias
*
* @private
*/
Builder.setAlias = function (alias) {
var aliasObject = {};
util_1.listDir(path_1.default.join(projectRoot, './src'), 1, []).forEach(function (dir) {
var name = dir.name, dirPath = dir.dirPath;
aliasObject['/' + name] = dirPath;
aliasObject[name] = dirPath;
});
if (util_1.isEmpty(alias)) {
return aliasObject;
}
return util_1.merge(alias, aliasObject);
};
/**
* 设置Loader的path查找的目录
* 目前已把本builder的node_modules也引入
* 好处是:把构建器放在 ./feflow 目录下,多个项目可以公用一个构建器,便于构建器的增量更新和统一升级
*/
Builder.setResolveLoaderPath = function (runtime) {
var jbRuntime = runtime || 'runtime-now-6';
var resolveLoaderPath = path_1.default.join(osenv_1.default.home(), './.feflow/node_modules');
// Loader在捷豹平台的查找路径
var jbLoaderPath = "/data/frontend/install/AlloyDist/" + jbRuntime + "/node_modules";
return {
modules: [
path_1.default.resolve(__dirname, "../node_modules"),
resolveLoaderPath,
jbLoaderPath,
]
};
};
/**
* 样式文件正则
*/
Builder.cssRegex = /\.css$/;
Builder.cssModulesRegex = /\.module\.css$/;
Builder.lessRegex = /\.less$/;
Builder.lessModulesRegex = /\.module\.less$/;
return Builder;
}());
exports.default = Builder;