Skip to content

Refactoring loaders into re-usable modules #22

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 13 additions & 95 deletions lib/config-generator.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ const ExtractTextPlugin = require('extract-text-webpack-plugin');
const ManifestPlugin = require('./webpack/webpack-manifest-plugin');
const DeleteUnusedEntriesJSPlugin = require('./webpack/delete-unused-entries-js-plugin');
const AssetOutputDisplayPlugin = require('./friendly-errors/asset-output-display-plugin');
const loaderFeatures = require('./loader-features');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const WebpackChunkHash = require('webpack-chunk-hash');
const FriendlyErrorsWebpackPlugin = require('friendly-errors-webpack-plugin');
Expand All @@ -23,6 +22,10 @@ const missingLoaderFormatter = require('./friendly-errors/formatters/missing-loa
const missingPostCssConfigTransformer = require('./friendly-errors/transformers/missing-postcss-config');
const missingPostCssConfigFormatter = require('./friendly-errors/formatters/missing-postcss-config');
const pathUtil = require('./config/path-util');
const cssLoaderUtil = require('./loaders/css');
const sassLoaderUtil = require('./loaders/sass');
const lessLoaderUtil = require('./loaders/less');
const babelLoaderUtil = require('./loaders/babel');

class ConfigGenerator {
/**
Expand Down Expand Up @@ -99,76 +102,18 @@ class ConfigGenerator {
}

buildRulesConfig() {
const cssLoaders = [
let rules = [
{
loader: 'css-loader' + this.getSourceMapOption() + (this.webpackConfig.isProduction() ? '?minimize=1' : ''),
// match .js and .jsx
test: /\.jsx?$/,
exclude: /(node_modules|bower_components)/,
use: babelLoaderUtil.getLoaders(this.webpackConfig)
},
];
if (this.webpackConfig.usePostCssLoader) {
loaderFeatures.ensureLoaderPackagesExist('postcss');

cssLoaders.push({
loader: 'postcss-loader' + this.getSourceMapOption(),
});
}

let babelConfig = {
// improves performance by caching babel compiles
// we add this option ALWAYS
// https://github.com/babel/babel-loader#options
cacheDirectory: true
};

// configure babel (unless the user is specifying .babelrc)
// todo - add a sanity check for their babelrc contents
if (!this.webpackConfig.doesBabelRcFileExist()) {
Object.assign(babelConfig, {
presets: [
['env', {
// modules don't need to be transformed - webpack will parse
// the modules for us. This is a performance improvement
// https://babeljs.io/docs/plugins/preset-env/#optionsmodules
modules: false,
targets: {
browsers: '> 1%',
uglify: true
},
useBuiltIns: true
}]
],
});

if (this.webpackConfig.useReact) {
loaderFeatures.ensureLoaderPackagesExist('react');

babelConfig.presets.push('react');
}

// allow for babel config to be controlled
this.webpackConfig.babelConfigurationCallback.apply(
// use babelConfig as the this variable
babelConfig,
[babelConfig]
);
}

let rules = [];
rules.push({
// match .js and .jsx
test: /\.jsx?$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: babelConfig
}
});

rules = rules.concat([
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader' + this.getSourceMapOption(),
use: cssLoaders
use: cssLoaderUtil.getLoaders(this.webpackConfig)
})
},
{
Expand All @@ -187,51 +132,24 @@ class ConfigGenerator {
publicPath: this.webpackConfig.getRealPublicPath()
}
},
]);
];

if (this.webpackConfig.useSassLoader) {
loaderFeatures.ensureLoaderPackagesExist('sass');

const sassLoaders = [...cssLoaders];
if (true === this.webpackConfig.sassOptions.resolve_url_loader) {
// responsible for resolving SASS url() paths
// without this, all url() paths must be relative to the
// entry file, not the file that contains the url()
sassLoaders.push({
loader: 'resolve-url-loader' + this.getSourceMapOption(),
});
}

sassLoaders.push({
loader: 'sass-loader',
options: {
// needed by the resolve-url-loader
sourceMap: (true === this.webpackConfig.sassOptions.resolve_url_loader) || this.webpackConfig.useSourceMaps
}
});

rules.push({
test: /\.s[ac]ss$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader' + this.getSourceMapOption(),
use: sassLoaders
use: sassLoaderUtil.getLoaders(this.webpackConfig)
})
});
}

if (this.webpackConfig.useLessLoader) {
loaderFeatures.ensureLoaderPackagesExist('less');

rules.push({
test: /\.less/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader' + this.getSourceMapOption(),
use: [
...cssLoaders,
{
loader: 'less-loader' + this.getSourceMapOption()
},
]
use: lessLoaderUtil.getLoaders(this.webpackConfig)
})
});
}
Expand Down
67 changes: 67 additions & 0 deletions lib/loaders/babel.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

'use strict';

const loaderFeatures = require('../loader-features');

/**
* @param {WebpackConfig} webpackConfig
* @return {Array} of loaders to use for Babel
*/
module.exports = {
getLoaders(webpackConfig) {
let babelConfig = {
// improves performance by caching babel compiles
// we add this option ALWAYS
// https://github.com/babel/babel-loader#options
cacheDirectory: true
};

// configure babel (unless the user is specifying .babelrc)
// todo - add a sanity check for their babelrc contents
if (!webpackConfig.doesBabelRcFileExist()) {
Object.assign(babelConfig, {
presets: [
['env', {
// modules don't need to be transformed - webpack will parse
// the modules for us. This is a performance improvement
// https://babeljs.io/docs/plugins/preset-env/#optionsmodules
modules: false,
targets: {
browsers: '> 1%',
uglify: true
},
useBuiltIns: true
}]
],
});

if (webpackConfig.useReact) {
loaderFeatures.ensureLoaderPackagesExist('react');

babelConfig.presets.push('react');
}

// allow for babel config to be controlled
webpackConfig.babelConfigurationCallback.apply(
// use babelConfig as the this variable
babelConfig,
[babelConfig]
);
}

return [
{
loader: 'babel-loader',
options: babelConfig
}
];
}
};
43 changes: 43 additions & 0 deletions lib/loaders/css.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

'use strict';

const loaderFeatures = require('../loader-features');

/**
* @param {WebpackConfig} webpackConfig
* @return {Array} of loaders to use for CSS files
*/
module.exports = {
getLoaders(webpackConfig) {
const cssLoaders = [
{
loader: 'css-loader',
options: {
minimize: webpackConfig.isProduction(),
sourceMap: webpackConfig.useSourceMaps
}
},
];

if (webpackConfig.usePostCssLoader) {
loaderFeatures.ensureLoaderPackagesExist('postcss');

cssLoaders.push({
loader: 'postcss-loader',
options: {
sourceMap: webpackConfig.useSourceMaps
}
});
}

return cssLoaders;
}
};
33 changes: 33 additions & 0 deletions lib/loaders/less.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

'use strict';

const loaderFeatures = require('../loader-features');
const cssLoader = require('./css');

/**
* @param {WebpackConfig} webpackConfig
* @return {Array} of loaders to use for Less files
*/
module.exports = {
getLoaders(webpackConfig) {
loaderFeatures.ensureLoaderPackagesExist('less');

return [
...cssLoader.getLoaders(webpackConfig),
{
loader: 'less-loader',
options: {
sourceMap: webpackConfig.useSourceMaps
}
},
];
}
};
46 changes: 46 additions & 0 deletions lib/loaders/sass.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

'use strict';

const loaderFeatures = require('../loader-features');
const cssLoader = require('./css');

/**
* @param {WebpackConfig} webpackConfig
* @return {Array} of loaders to use for Sass files
*/
module.exports = {
getLoaders(webpackConfig) {
loaderFeatures.ensureLoaderPackagesExist('sass');

const sassLoaders = [...cssLoader.getLoaders(webpackConfig)];
if (true === webpackConfig.sassOptions.resolve_url_loader) {
// responsible for resolving SASS url() paths
// without this, all url() paths must be relative to the
// entry file, not the file that contains the url()
sassLoaders.push({
loader: 'resolve-url-loader',
options: {
sourceMap: webpackConfig.useSourceMaps
}
});
}

sassLoaders.push({
loader: 'sass-loader',
options: {
// needed by the resolve-url-loader
sourceMap: (true === webpackConfig.sassOptions.resolve_url_loader) || webpackConfig.useSourceMaps
}
});

return sassLoaders;
}
};
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
"nsp": "^2.6.3",
"postcss-loader": "^1.3.3",
"sass-loader": "^6.0.3",
"sinon": "^2.3.4",
"zombie": "^5.0.5"
}
}
Loading