Skip to content

Commit

Permalink
refactor: loader merge
Browse files Browse the repository at this point in the history
  • Loading branch information
hubcarl committed Nov 20, 2018
1 parent b1fc3f1 commit a3649ba
Show file tree
Hide file tree
Showing 5 changed files with 210 additions and 165 deletions.
20 changes: 1 addition & 19 deletions config/loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,25 +28,7 @@ exports.ts = {
test: /\.tsx?$/,
exclude: /node_modules/,
use() {
const loaders = [];
const createTsLoader = options => {
return { loader: 'ts-loader', options };
};
const compile = this.config.compile;
if (compile.thread) {
loaders.unshift(this.createThreadLoader(compile.thread));
loaders.push(createTsLoader({ happyPackMode: true }));
} else {
loaders.push(createTsLoader());
}
if (compile.cache) {
loaders.unshift(this.createCacheLoader(compile.cache));
}
// react typescript need to dynamic import
if (this.typescript && this.framework === 'react') {
loaders.unshift(this.createBabelLoader());
}
return loaders;
return this.createTsLoader();
}
};

Expand Down
10 changes: 10 additions & 0 deletions lib/core/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ class Config {
this.initialize(this.config);
this.initEnv(this.config);
this.initBabelrc();
this.initLoader();
}

get egg() {
Expand Down Expand Up @@ -170,6 +171,15 @@ class Config {
return this._babelConfig;
}

get loaderOptions() {
if (this._loaderOptions) {
return this._loaderOptions;
}
this._loaderOptions = this.merge(this.config.loaderOptions, this.loaders.options);
return this._loaderOptions;
}


initZero(config) {
if (this.egg) {
zero.initEggDefault(config);
Expand Down
102 changes: 64 additions & 38 deletions lib/core/loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,14 @@ module.exports = {
if (loaders[name]) {
return loaders[name];
}
const mappingName = this.loaderKeyLabelMapping[name];

const mappingName = Object.keys(this.refactorLoaderMapping).find(tmpKey => {
return this.refactorLoaderMapping[tmpKey] === name;
});
if (loaders[mappingName]) {
return loaders[mappingName];
}

return rules.find(loader => {
const label = this.utils.getLoaderLabel(loader);
if (name === label || mappingName === label) {
Expand All @@ -29,10 +36,51 @@ module.exports = {

getLoaderByName(name) {
const defaultLoader = this.utils.cloneDeep(this.loaders[name]);
const configLoader = this.getConfigLoaderByName(this.config);
return this.mergeLoader({ [name]: defaultLoader }, { [name]: configLoader })[name];
const configLoader = this.getConfigLoaderByName(name);
return this.mergeLoader({ [name]: configLoader }, { [name]: defaultLoader })[name];
},

initLoader() {
// 默认 typescript 开启, tslint 开启,eslint 禁用
if (this.typescript) {
this.setExtensions(['.ts'], false);
// egg project, auto set client typescript tsconfig.json config
if (this.egg) {
const configFile = path.join(this.baseDir, './app/web/tsconfig.json');
if (fs.existsSync(configFile)) {
this.mergeLoader({
ts: {
options: {
configFile
}
}
});
}
}
}
},

createTsLoader() {
const loaders = [];
const createTsLoader = options => {
return { loader: 'ts-loader', options };
};
const compile = this.config.compile;
if (compile.thread) {
loaders.unshift(this.createThreadLoader(compile.thread));
loaders.push(createTsLoader({ happyPackMode: true }));
} else {
loaders.push(createTsLoader());
}
if (compile.cache) {
loaders.unshift(this.createCacheLoader(compile.cache));
}
// react typescript need to dynamic import
if (this.typescript && this.framework === 'react') {
loaders.unshift(this.createBabelLoader());
}
return loaders;
},

createPostCssLoader(loaderOptions) {
const loader = 'postcss-loader';
Expand Down Expand Up @@ -127,20 +175,20 @@ module.exports = {
}
});
}
Object.keys(sourceLoaders).forEach(label => {
const sourceLoader = sourceLoaders[label];
const name = this.refactorLoaderMapping[label] || label;
if (sourceLoader.loader) { // single loader config
Object.keys(sourceLoaders).forEach(key => {
const sourceLoader = sourceLoaders[key];
if (this.utils.isObject(sourceLoader) && sourceLoader.loader) { // single loader config
sourceLoader.use = [{ loader: sourceLoader.loader, options: sourceLoader.options || {} }];
}
const name = this.refactorLoaderMapping[key] || key;
const loader = target[name];
if (loader) {
if (this.utils.isObject(sourceLoader) && sourceLoader.enable === undefined) {
target[name].enable = true;
}
if (this.utils.isBoolean(sourceLoader)) {
target[name].enable = sourceLoader;
} else if (sourceLoader.use) {
} else if (this.utils.isObject(sourceLoader) && sourceLoader.use) {
target[name] = this.merge(target[name], sourceLoader);
target[name].use = sourceLoader.use;
} else if (this.utils.isObject(sourceLoader) && !this.hasRuleKey(sourceLoader)) {
Expand All @@ -156,10 +204,7 @@ module.exports = {
return target;
},


prepareCssModuleLoader(loaders) {},

prepareLoaderOption(loaders, loaderOptions) {
mergeLoaderOption(loaders, loaderOptions) {
const extract = this.isUse('extract');
Object.keys(loaders).forEach(name => {
const itemLoader = loaders[name];
Expand Down Expand Up @@ -200,6 +245,12 @@ module.exports = {
return loaders;
},

prepareCssModuleLoader(loaders) {},

prepareLoaderOption(loaders, loaderOptions) {
return this.mergeLoaderOption(loaders, loaderOptions);
},

createLoader(loaders) {
const webpackLoaders = [];
const loaderNames = Object.keys(loaders).filter(name => {
Expand Down Expand Up @@ -268,7 +319,7 @@ module.exports = {
});
// https://github.com/TypeStrong/ts-loader/pull/782
// vue-loader 14 版本中,需在 options 重复配置 ts-loader,升级 15 以后可移除
if (this.typescript && !loaders.ts) {
if (this.typescript) {
const use = this.utils.isFunction(this.typescript.use) ? this.typescript.use.apply(this) : this.typescript.use;
const tsLoader = use.find(item => {
return item.loader === 'ts-loader';
Expand All @@ -287,35 +338,10 @@ module.exports = {
return webpackLoaders;
},

adapterTSLoader(loaders) {
// 默认 typescript 开启, tslint 开启,eslint 禁用
if (this.typescript) {
this.setExtensions(['.ts'], false);
// egg project, auto set client typescript tsconfig.json config
if (this.egg) {
const configFile = path.join(this.baseDir, './app/web/tsconfig.json');
if (fs.existsSync(configFile)) {
this.mergeLoader({
ts: {
options: {
configFile
}
}
});
}
}
}
},

adapterLoader(loaders) {
this.adapterTSLoader(loaders);
},

createWebpackLoader(config) {
const { loaders, rules } = this.getConfigLoader(config);
this.mergeLoader(loaders);
this.mergeLoader(rules);
this.adapterLoader(this.loaders);
this.prepareCssModuleLoader(this.loaders);
this.prepareLoaderOption(this.loaders, this.merge(config.loaderOptions, this.loaders.options));
return this.installLoader(this.loaders);
Expand Down
101 changes: 1 addition & 100 deletions test/client.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -292,106 +292,7 @@ describe('client.test.js', () => {
});
});

describe('#webpack typescript test', () => {
it('should default typescript enable test', () => {
const builder = createBuilder();
const webpackConfig = builder.create();
const tsLoader = helper.getLoaderByName('ts', webpackConfig.module.rules);
const tslint = helper.getLoaderByName('tslint', webpackConfig.module.rules);
expect(tsLoader).to.be.undefined;
expect(tslint).to.be.undefined;
});

it('should typescript cache enable test', () => {
const builder = createBuilder({
loaders:{
eslint: true,
tslint: true,
typescript: true
},
compile:{
thread: false
}
});
const webpackConfig = builder.create();
const tsLoader = helper.getLoaderByName('ts', webpackConfig.module.rules);
const eslint = helper.getLoaderByName('eslint', webpackConfig.module.rules);
const tslint = helper.getLoaderByName('tslint', webpackConfig.module.rules);
expect(tsLoader.use[0].loader).to.equal('cache-loader');
expect(tsLoader.use[1].loader).to.equal('ts-loader');
expect(eslint.use[0].loader).to.equal('eslint-loader');
expect(tslint.use[0].loader).to.equal('tslint-loader');
expect(webpackConfig.resolve.extensions).to.include.members(['.ts', '.js']);
});

it('should typescript cache and thread enable test', () => {
const builder = createBuilder({
loaders:{
eslint: true,
tslint: true,
typescript: true
}
});
const webpackConfig = builder.create();
const tsLoader = helper.getLoaderByName('ts', webpackConfig.module.rules);
const eslint = helper.getLoaderByName('eslint', webpackConfig.module.rules);
const tslint = helper.getLoaderByName('tslint', webpackConfig.module.rules);
expect(tsLoader.use[0].loader).to.equal('cache-loader');
expect(tsLoader.use[1].loader).to.equal('thread-loader');
expect(tsLoader.use[2].loader).to.equal('ts-loader');
expect(eslint.use[0].loader).to.equal('eslint-loader');
expect(tslint.use[0].loader).to.equal('tslint-loader');
expect(webpackConfig.resolve.extensions).to.include.members(['.ts', '.js']);
});

it('should typescript cache config test', () => {
const configFile = path.resolve(__dirname, './app/web/tsconfig.json');
const builder = createBuilder({
loaders:{
typescript: {
options:{
configFile,
}
}
},
compile:{
thread: false
}
});
const webpackConfig = builder.create();
const tsLoader = helper.getLoaderByName('ts', webpackConfig.module.rules);
const eslint = helper.getLoaderByName('eslint', webpackConfig.module.rules);
const tslint = helper.getLoaderByName('tslint', webpackConfig.module.rules);
expect(eslint).to.be.undefined;
expect(tslint).to.be.undefined;
expect(tsLoader.use[0].loader).to.equal('cache-loader');
expect(tsLoader.use[1].loader).to.equal('ts-loader');
expect(tsLoader.use[1].options.configFile).to.equal(configFile);
});

it('should tslint enable test', () => {
const builder = createBuilder({
loaders:{
tslint: true
}
});
const webpackConfig = builder.create();
const tsLoader = helper.getLoaderByName('tslint', webpackConfig.module.rules);
expect(tsLoader.use[0].loader).to.equal('tslint-loader');
});

it('should typescript egg configFile auto set test', () => {
const builder = createBuilder({
egg: true,
loaders:{
typescript: true
}
});
const webpackConfig = builder.create();
const tsLoader = helper.getLoaderByName('ts', webpackConfig.module.rules);
expect(tsLoader.use[2].loader).to.equal('ts-loader');
});

describe('#webpack service worker test', () => {

it('should service worker default test', () => {
const builder = createBuilder({});
Expand Down
Loading

0 comments on commit a3649ba

Please sign in to comment.