示例目录结构如下所示:
当前:
example/
├── src/
│ ├── fonts/
│ │ └── OpenSans/
│ │ ├── OpenSans-Regular.woff
│ │ └── ...
│ ├── js/
│ │ └── ...
│ ├── css/
│ │ ├── base/
│ │ │ ├── _font.scss
│ │ │ └── ...
│ │ └── ...
│ ├── app.js
├── web/
│ ├── build/
│ │ ├── fonts/
│ │ │ ├── OpenSans-Regular.woff
│ │ │ └── ...
│ │ ├── app.css
│ │ ├── app.es5.js
│ │ └── app.js
│ └── index.php
├── webpack.common.js
├── webpack.dev.js
└── webpack.prod.js
目标:
example/
├── src/
│ ├── js/
│ │ └── ...
│ ├── css/
│ │ ├── base/
│ │ │ ├── _font.scss
│ │ │ └── ...
│ │ └── ...
│ ├── app.js
├── web/
│ ├── build/
│ │ ├── app.css
│ │ ├── app.es5.js
│ │ └── app.js
│ ├── fonts/
│ │ └── OpenSans/
│ │ ├── OpenSans-Regular.woff
│ │ └── ...
│ └── index.php
├── webpack.common.js
├── webpack.dev.js
└── webpack.prod.js
我现在需要参考浏览器最终如何需要这些字体文件。这可能看起来像:
_font.scss
当前:
@font-face {
font-family: 'Open Sans';
src: url('../../fonts/OpenSans/OpenSans-Regular.eot');
src: local('Open Sans Regular'), local('OpenSans-Regular'),
url('../../fonts/OpenSans/OpenSans-Regular.eot?#iefix') format('embedded-opentype'),
url('../../fonts/OpenSans/OpenSans-Regular.woff2') format('woff2'),
url('../../fonts/OpenSans/OpenSans-Regular.woff') format('woff'),
url('../../fonts/OpenSans/OpenSans-Regular.ttf') format('truetype'),
url('../../fonts/OpenSans/OpenSans-Regular.svg#OpenSans-Regular') format('svg');
font-weight: normal;
font-style: normal;
font-display: swap;
}
目标:
@font-face {
font-family: 'Open Sans';
src: url('/fonts/OpenSans/OpenSans-Regular.eot');
src: local('Open Sans Regular'), local('OpenSans-Regular'),
url('/fonts/OpenSans/OpenSans-Regular.eot?#iefix') format('embedded-opentype'),
url('/fonts/OpenSans/OpenSans-Regular.woff2') format('woff2'),
url('/fonts/OpenSans/OpenSans-Regular.woff') format('woff'),
url('/fonts/OpenSans/OpenSans-Regular.ttf') format('truetype'),
url('/fonts/OpenSans/OpenSans-Regular.svg#OpenSans-Regular') format('svg');
font-weight: normal;
font-style: normal;
font-display: swap;
}
显然,我可以将字体文件放在源文件夹中并将它们包含在构建中(这是目前的情况),但这是不必要的。此外,从项目根目录中引用与 scss 文件相关的字体文件或绝对文件,但这只是将文件复制到 build/ 文件夹。这使得构建不必要地更长和更重。
我只是想把 url 放在 scss 文件中,构建过程应该简单地复制值,没有解析,没有改变,什么都没有,只是复制。
有关更多上下文,以下是当前的 webpack 文件:
webpack.common.js
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const del = require('del');
const { WebpackManifestPlugin } = require('webpack-manifest-plugin');
const RemoveEmptyScriptsPlugin = require('webpack-remove-empty-scripts');
/*
* https://github.com/chrisblossom/clean-self-webpack-plugin
* Remove project files before webpack is loaded.
* Be sure it is not async.
*
* It is HIGHLY recommended to handle the initial
* build directory clean outside of this plugin / webpack.
*
* Popular existing packages:
* https://github.com/isaacs/rimraf
* https://github.com/sindresorhus/del
* -- I prefer this one, great glob support and has CLI (del-cli package)
* https://github.com/jprichardson/node-fs-extra
*/
del.sync([path.resolve(__dirname, 'web', 'build', '**/*')]);
exports.common = {
entry: {
app: './src/app.js',
styleguide: './src/styleguide.js',
},
output: {
path: path.resolve(__dirname, 'web', 'build'),
publicPath: '/build/',
},
module: {
rules: [
{
test: /\.s[ac]ss$/i,
use: [
// This plugin extracts CSS into separate files.
{
loader: MiniCssExtractPlugin.loader,
options: {},
},
// Translates CSS into CommonJS
{
loader: 'css-loader',
options: { sourceMap: true }
},
// A tool for transforming CSS with JavaScript
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [
require('postcss-import')({
plugins: [
],
path: ['./node_modules'],
}),
require('tailwindcss'),
require('postcss-preset-env')({
autoprefixer: {},
features: {
'nesting-rules': true,
// https://github.com/tailwindlabs/tailwindcss/issues/1190
// BUG: ... from Css Minimizer. Expected an opening square bracket.
'focus-within-pseudo-class': false,
}
}),
]
},
sourceMap: true
}
},
// A webpack loader that rewrites relative paths in url()
// statements based on the original source file.
{
loader: 'resolve-url-loader',
options: { sourceMap: true }
},
// Compiles Sass to CSS
{
loader: 'sass-loader',
options: { sourceMap: true }
},
],
},
{
test: /fonts\/(.*)\.(woff(2)?|ttf|eot|svg)$/,
type: 'asset/resource',
generator: {
filename: 'fonts/[name][ext][query]'
}
},
{
test: /img\/(.*)\.(jp(e)?g|png|gif|svg)$/,
type: 'asset/resource',
generator: {
filename: 'img/[name][ext][query]'
}
}
],
},
plugins: [
/**
* Remove .js files of sass entrypoint.
*/
new RemoveEmptyScriptsPlugin(),
]
};
exports.jsModern = {
module: {
rules: [
{
test: /\.m?js$/,
exclude: /node_modules/,
use: [
{
loader: 'babel-loader',
options: {
presets: [
['@babel/preset-env', {
modules: false,
useBuiltIns: 'entry',
corejs: '3.12',
targets: {
browsers: [
'Chrome >= 60',
'Safari >= 10.1',
'iOS >= 10.3',
'Firefox >= 54',
'Edge >= 15',
],
},
}]
],
cacheDirectory: true,
}
}
],
},
]
},
target: ['web', 'es6'],
plugins: [
/**
* A Webpack plugin for generating an asset manifest.
*/
new WebpackManifestPlugin(),
],
};
exports.jsLegacy = {
module: {
rules: [
{
test: /\.m?js$/,
exclude: /node_modules/,
use: [
{
loader: 'babel-loader',
options: {
presets: [
['@babel/preset-env', {
modules: false,
useBuiltIns: 'entry',
corejs: '3.12',
targets: {
browsers: [
'> 1%',
'last 2 versions',
'Firefox ESR',
],
},
}]
],
cacheDirectory: true,
}
}
],
},
]
},
target: ['web', 'es5'],
plugins: [
/**
* A Webpack plugin for generating an asset manifest.
*/
new WebpackManifestPlugin({
fileName: 'manifest-legacy.json',
}),
],
};
webpack.dev.js
const { merge } = require('webpack-merge');
const { common, jsLegacy, jsModern } = require('./webpack.common.js');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const WebpackBar = require('webpackbar');
const dev = merge(common, {
mode: 'development',
devtool: 'inline-source-map',
plugins: [
/**
* This plugin extracts CSS into separate files. It creates a CSS file per
* JS file which contains CSS. It supports On-Demand-Loading of CSS and
* SourceMaps.
*/
new MiniCssExtractPlugin({
filename: '[name].css'
}),
new WebpackBar({}),
]
});
module.exports = [
merge(dev, jsModern, {
name: 'modern',
output: {
filename: '[name].js',
},
}),
merge(dev, jsLegacy, {
name: 'legacy',
output: {
filename: '[name].es5.js',
},
})
];
module.exports.parallelism = 1;
有人知道如何实现吗?还是不可能?