Skip to content
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

Add alias feature to rewrite urls #274

Merged
merged 3 commits into from
Mar 18, 2017
Merged
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
41 changes: 40 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ To be compatible with existing css files (if not in CSS Module mode):
|**`sourceMap`**|`false`|Enable/Disable Sourcemaps|
|**`camelCase`**|`false`|Export Classnames in CamelCase|
|**`importLoaders`**|`0`|Number of loaders applied before CSS loader|
|**`alias`**|`{}`|Create aliases to import certain modules more easily|

The following webpack config can load CSS files, embed small PNG/JPG/GIF/SVG images as well as fonts as [Data URLs](https://tools.ietf.org/html/rfc2397) and copy larger files to the output directory.

Expand Down Expand Up @@ -322,7 +323,7 @@ They are not enabled by default because they expose a runtime overhead and incre

### toString

You can also use the css-loader results directly as string, such as in Angular's component style.
You can also use the css-loader results directly as string, such as in Angular's component style.

**webpack.config.js**

Expand Down Expand Up @@ -430,6 +431,44 @@ By default, the exported JSON keys mirror the class names. If you want to cameli
import { className } from 'file.css';
```

### Alias

Rewrite your urls with alias, this is useful when it's hard to change url paths of your input files, for example, when you're using some css / sass files in another package (bootstrap, ratchet, font-awesome, etc.).

#### Possible Options

css-loader's `alias` follows the same syntax as webpack's `resolve.alias`, you can see the details at: https://webpack.js.org/configuration/resolve/#resolve-alias

**webpack.config.js**
```js
{
test: /\.scss$/,
use: [{
loader: "style-loader"
}, {
loader: "css-loader",
options: {
alias: {
"../fonts/bootstrap": "bootstrap-sass/assets/fonts/bootstrap"
}
}
}, {
loader: "sass-loader",
options: {
includePaths: [
path.resolve("./node_modules/bootstrap-sass/assets/stylesheets")
]
}
}]
}
```

```scss
@charset "UTF-8";
@import "bootstrap";
```
Check out this [working bootstrap example](https://github.com/bbtfr/webpack2-bootstrap-sass-sample).

<h2 align="center">Maintainers</h2>

<table>
Expand Down
36 changes: 36 additions & 0 deletions lib/createResolver.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
module.exports = function createResolver(alias) {
if(typeof alias !== "object" || Array.isArray(alias)) {
return function(url) {
return url
};
}

alias = Object.keys(alias).map(function(key) {
var onlyModule = false;
var obj = alias[key];
if(/\$$/.test(key)) {
onlyModule = true;
key = key.substr(0, key.length - 1);
}
if(typeof obj === "string") {
obj = {
alias: obj
};
}
obj = Object.assign({
name: key,
onlyModule: onlyModule
}, obj);
return obj;
});

return function(url) {
alias.forEach(function(obj) {
var name = obj.name;
if(url === name || (!obj.onlyModule && url.startsWith(name + "/"))) {
url = obj.alias + url.substr(name.length);
}
});
return url;
}
}
4 changes: 3 additions & 1 deletion lib/loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ var loaderUtils = require("loader-utils");
var processCss = require("./processCss");
var getImportPrefix = require("./getImportPrefix");
var compileExports = require("./compile-exports");
var createResolver = require("./createResolver");


module.exports = function(content, map) {
Expand All @@ -15,6 +16,7 @@ module.exports = function(content, map) {
var root = query.root;
var moduleMode = query.modules || query.module;
var camelCaseKeys = query.camelCase || query.camelcase;
var resolve = createResolver(query.alias);

if(map !== null && typeof map !== "string") {
map = JSON.stringify(map);
Expand Down Expand Up @@ -69,7 +71,7 @@ module.exports = function(content, map) {
var match = result.urlItemRegExp.exec(item);
var idx = +match[1];
var urlItem = result.urlItems[idx];
var url = urlItem.url;
var url = resolve(urlItem.url);
idx = url.indexOf("?#");
if(idx < 0) idx = url.indexOf("#");
var urlRequest;
Expand Down
30 changes: 30 additions & 0 deletions test/aliasTest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*globals describe */

var test = require("./helpers").test;

describe("alias", function() {
var css = ".className { background: url(./path/to/file.png); }";
var exports = {
without: [
[1, ".className { background: url({./path/to/file.png}); }", ""]
],
onlyModule: [
[1, ".className { background: url({module/file.png}); }", ""]
],
exactMatch: [
[1, ".className { background: url({module/file.png}); }", ""]
],
notExactMatch: [
[1, ".className { background: url({./path/to/file.png}); }", ""]
]
};

function aliasOptions(alias) {
return { query: { alias: alias }}
}

test("without", css, exports.without);
test("onlyModule", css, exports.onlyModule, aliasOptions({ "./path/to": "module" }));
test("exactMatch", css, exports.exactMatch, aliasOptions({ "./path/to/file.png$": "module/file.png" }));
test("notExactMatch", css, exports.notExactMatch, aliasOptions({ "./path/to/file.jpg$": "module/file.jpg" }));
});