webpack 將 Less 編譯為 CSS 的 loader。
首先,你需要先安裝 less 和 less-loader:
$ npm install less less-loader --save-dev
然后將該 loader 添加到 webpack 的配置中去,例如:
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.less$/i,
use: [
// compiles Less to CSS
'style-loader',
'css-loader',
'less-loader',
],
},
],
},
};
接著使用你習(xí)慣的方式運行 webpack。
名稱 | 類型 | 默認(rèn)值 | 描述 |
---|---|---|---|
lessOptions
|
{Object|Function}
|
{ relativeUrls: true }
|
Less 的可選項。 |
additionalData
|
{String|Function}
|
undefined
|
在入口文件起始或末尾添加 Less 代碼。 |
sourceMap
|
{Boolean}
|
compiler.devtool
|
是否生成 source map。 |
webpackImporter
|
{Boolean}
|
true
|
是否啟用默認(rèn)的 webpack importer。 |
implementation
|
{Object|String}
|
less
|
配置 Less 使用的實現(xiàn)庫 |
類型: ?Object|Function
? 默認(rèn)值: { relativeUrls: true }
通過 lessOptions 屬性,你可以設(shè)置 loader options 中的任意特定的選項值給 less-loader。所有可用的選項值請參看 Less 命令行可選參數(shù)文檔。由于我們是通過編程的方式將這些選項傳遞給 Less,因此您需要將破折號(dash-case)轉(zhuǎn)換為駝峰值(camelCase)后傳遞它們。
使用對象(Object)的形式傳遞 options 給 Less。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.less$/i,
use: [
{
loader: 'style-loader',
},
{
loader: 'css-loader',
},
{
loader: 'less-loader',
options: {
lessOptions: {
strictMath: true,
},
},
},
],
},
],
},
};
允許根據(jù) loader 的 context 來設(shè)置 options,再傳遞給 Less。
module.exports = {
module: {
rules: [
{
test: /\.less$/i,
use: [
'style-loader',
'css-loader',
{
loader: 'less-loader',
options: {
lessOptions: (loaderContext) => {
// 更多可用的屬性見 https://webpack.js.org/api/loaders/
const { resourcePath, rootContext } = loaderContext;
const relativePath = path.relative(rootContext, resourcePath);
if (relativePath === 'styles/foo.less') {
return {
paths: ['absolute/path/c', 'absolute/path/d'],
};
}
return {
paths: ['absolute/path/a', 'absolute/path/b'],
};
},
},
},
],
},
],
},
};
類型: ?String|Function
? 默認(rèn)值: undefined
在實際入口文件的起始位置添加 Less 代碼。 這種情況下,less-loader 只會追加并不會覆蓋文件內(nèi)容。
當(dāng)你的 Less 變量依賴環(huán)境變量時這個屬性將非常有用:
? 由于你注入了代碼,因此它將破壞入口文件的源映射關(guān)系。通常有比這更簡單的解決方案,例如多個 Less 入口文件。
module.exports = {
module: {
rules: [
{
test: /\.less$/i,
use: [
'style-loader',
'css-loader',
{
loader: 'less-loader',
options: {
additionalData: `@env: ${process.env.NODE_ENV};`,
},
},
],
},
],
},
};
module.exports = {
module: {
rules: [
{
test: /\.less$/i,
use: [
'style-loader',
'css-loader',
{
loader: 'less-loader',
options: {
additionalData: (content, loaderContext) => {
// 更多可用的屬性見 https://webpack.js.org/api/loaders/
const { resourcePath, rootContext } = loaderContext;
const relativePath = path.relative(rootContext, resourcePath);
if (relativePath === 'styles/foo.less') {
return '@value: 100px;' + content;
}
return '@value: 200px;' + content;
},
},
},
],
},
],
},
};
module.exports = {
module: {
rules: [
{
test: /\.less$/i,
use: [
'style-loader',
'css-loader',
{
loader: 'less-loader',
options: {
additionalData: async (content, loaderContext) => {
// More information about available properties https://webpack.js.org/api/loaders/
const { resourcePath, rootContext } = loaderContext;
const relativePath = path.relative(rootContext, resourcePath);
if (relativePath === 'styles/foo.less') {
return '@value: 100px;' + content;
}
return '@value: 200px;' + content;
},
},
},
],
},
],
},
};
類型: ?Boolean
? 默認(rèn)值: 取決于 compiler.devtool 的值
默認(rèn)生成的 source map 取決于 compiler.devtool 的值。除了值等于 eval 和 false 外,其他值都能生成 source map
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.less$/i,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
sourceMap: true,
},
},
{
loader: 'less-loader',
options: {
sourceMap: true,
},
},
],
},
],
},
};
類型:?Boolean
? 默認(rèn)值:true
啟用/禁用 webpack 默認(rèn)的 importer。
在某些情況下,這樣做可以提高性能,但是請慎用,因為可能會使得 aliases 和以 ~ 開頭的 @import 規(guī)則失效。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.less$/i,
use: [
'style-loader',
'css-loader',
{
loader: 'less-loader',
options: {
webpackImporter: false,
},
},
],
},
],
},
};
類型:?Object | String
?
? less-loader 已兼容 Less 3 和 Less 4。
特殊的 implementation 選項決定使用 Less 的哪個實現(xiàn)。重載本地安裝的 less 的 peerDependency 版本。
此選項只對下游的工具作者有效,以便于 Less 3 到 Less 4 的過渡。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.less$/i,
use: [
'style-loader',
'css-loader',
{
loader: 'less-loader',
options: {
implementation: require('less'),
},
},
],
},
],
},
};
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.less$/i,
use: [
'style-loader',
'css-loader',
{
loader: 'less-loader',
options: {
implementation: require.resolve('less'),
},
},
],
},
],
},
};
將 less-loader、css-loader 和 style-loader 串聯(lián)起來使用可立即將所有樣式應(yīng)用于 DOM。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.less$/i,
use: [
{
loader: 'style-loader', // 從 JS 中創(chuàng)建樣式節(jié)點
},
{
loader: 'css-loader', // 轉(zhuǎn)化 CSS 為 CommonJS
},
{
loader: 'less-loader', // 編譯 Less 為 CSS
},
],
},
],
},
};
不幸的是,Less 并沒有將所有選項 1 對 1 映射為 camelCase(駝峰值)。如有疑問,請檢查執(zhí)行文件并搜索破折號選項。
為了生成 CSS 的 source map, 你需要在 loader 的可選項中設(shè)置 sourceMap 屬性。如果沒設(shè)置的話 loader 將會繼承你 webpack 中為生成 source map 設(shè)置的屬性值 devtool。
webpack.config.js
module.exports = {
devtool: 'source-map', // 任何類似于 "source-map" 的 devtool 值都可以
module: {
rules: [
{
test: /\.less$/i,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
sourceMap: true,
},
},
{
loader: 'less-loader',
options: {
sourceMap: true,
},
},
],
},
],
},
};
如果你想在 Chrome 中修改原始的 Less 文件,可以參考這篇不錯的博客。這篇博客雖然寫的 Sass,但也適合于 Less。
在生產(chǎn)環(huán)境中推薦使用 MiniCssExtractPlugin 來提取樣式表到專門的文件中,這樣你的樣式就不需要依賴 JavaScript。
首先我們會嘗試使用內(nèi)置 less 解析邏輯,然后再使用 webpack 解析邏輯(alias 和 ~)。
webpack 提供了一種 解析文件的高級機制。如果 less 不能解析 @import 的話,less-loader 作為 Less 的插件將所有的查詢結(jié)果傳遞給 webpack 解析器。因此你可以從 node_modules 中導(dǎo)入 Less 模塊。
@import "bootstrap/less/bootstrap";
~ 用法已被廢棄,可以從代碼中刪除(我們建議這么做),但是我們會因為一些歷史原因一直支持這種寫法。 為什么你可以移除它呢?loader 首先會嘗試以相對路徑解析 @import,如果它不能被解析,loader 將會嘗試在 node_modules 中解析 @import。 只要在包名前加上 ~,告訴 webpack 在 modules 中進行查找。
@import "~bootstrap/less/bootstrap";
可以通過 resolve.byDependency 修改默認(rèn)解析器配置:
webpack.config.js
module.exports = {
devtool: 'source-map', // "source-map" 類的 devtool 都是可以的
module: {
rules: [
{
test: /\.less$/i,
use: ['style-loader', 'css-loader', 'less-loader'],
},
],
},
resolve: {
byDependency: {
// 更多的配置項可以在這里找到 https://webpack.js.org/configuration/resolve/
less: {
mainFiles: ['custom'],
},
},
},
};
在其前面加上 ? 很關(guān)鍵,因為 ?/ 會解析到根目錄。webpack 需要區(qū)分 bootstrap 和 ?bootstrap,因為 CSS 和 Less 文件沒有用于導(dǎo)入相對路徑文件的特殊語法。寫 @import“ file” 等同于 @import“ ./file”;
如果指定 paths 選項,將從指定的 paths 中搜索模塊,這是 less 的默認(rèn)行為。paths 應(yīng)該是具有絕對路徑的數(shù)組:
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.less$/i,
use: [
{
loader: 'style-loader',
},
{
loader: 'css-loader',
},
{
loader: 'less-loader',
options: {
lessOptions: {
paths: [path.resolve(__dirname, 'node_modules')],
},
},
},
],
},
],
},
};
想要使用 插件,只需要簡單設(shè)置下 plugins 選項即可, 具體配置如下:
webpack.config.js
const CleanCSSPlugin = require('less-plugin-clean-css');
module.exports = {
...
{
loader: 'less-loader',
options: {
lessOptions: {
plugins: [
new CleanCSSPlugin({ advanced: true }),
],
},
},
},
...
};
?? 使用 pluginManager.webpackLoaderContext 屬性可以訪問自定義插件中的 loader context。
module.exports = {
install: function (less, pluginManager, functions) {
functions.add('pi', function () {
// Loader context is available in `pluginManager.webpackLoaderContext`
return Math.PI;
});
},
};
通過 webpack 打包 CSS 有很多好處,比如給引用圖片和字體文件路徑添加 hash, 在開發(fā)環(huán)境可以 模塊熱替換。另一方面,在生產(chǎn)環(huán)境,根據(jù) JS 來控制應(yīng)用樣式表不是一個好的方式,可能會導(dǎo)致延遲渲染,甚至可能會出現(xiàn)閃爍現(xiàn)象。因此,在你最終的生產(chǎn)環(huán)境中將它們拆分成單獨的文件來存放通常是比較好的選擇。
有兩種從 bundle 中提取樣式表的方式:
extract-loader
? (簡單,但得專門指定 css-loader 的 output)MiniCssExtractPlugin
? (較復(fù)雜,但適用于所有的場景)Less 和 CSS modules 有一個已知的問題,關(guān)于 url(...) 語句中的相對文件路徑,看下這個問題的解釋。
如果你還沒有看過我們的貢獻者指南請先花點時間看一下。
更多建議: