참고 : https://stackoverflow.com/questions/48475500/webpack-scss-how-to-work-with-image-paths
현재상황
파일 구조

style.scss
#page {
overflow: hidden;
.bg{
background:url('./assets/bg.png') no-repeat;
overflow:hidden;
}
....
webpack.config.js
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const join = require('path').join;
module.exports = {
entry: join(__dirname, '/src/main.ts'),
devtool: 'source-map',
output: {
filename: "main.js",
path: join(__dirname, '/dist'),
},
module: {
rules: [
{
test: /\.(ts|tsx)$/,
exclude: /node_modules/,
use: 'ts-loader'
},
{
test: /\.(scss|css)$/,
use: [MiniCssExtractPlugin.loader, "css-loader", "sass-loader"]
},
]
},
plugins: [
new MiniCssExtractPlugin({
filename: "style.css",
}),
new HtmlWebpackPlugin({
template: join(__dirname, '/src/index.html')
}),
new CleanWebpackPlugin({
cleanAfterEveryBuildPatterns: ['dist']
}),
],
resolve: {
extensions: ['.js', '.ts', '.json', 'scss']
}
};
내가 원하는 상황
webpack을 빌드하면 dist폴더의 구조는 아래와 같이 되고

style.css파일안에서 background-image를 지정하는 부분은
.bg {
background:url(./assets/bg.png)
}
이렇게 되는것이다.
일단 Build해보자
에러가 따-악
ERROR in ./src/style.scss
Module build failed (from ./node_modules/mini-css-extract-plugin/dist/loader.js):
ModuleParseError: Module parse failed: Unexpected character '�' (1:0)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
You may need an appropriate loader to handle this file type
OK, 내 추측으로는 style.scss
파일의 url('./assets/bg.png')
가 문제인것같다. 이 코드를 처리할 수 있는 loader가 없다는 의미인듯.
file-loader를 설치해보자고
이렇게 파일을 처리해야 하는경우 file-loader가 필요하다.
npm install --save-dev file-loader
그리고 webpack.config.js
도 아래와 같이 변경해준다.
rules: [
{
test: /\.(png|jpe?g|gif)$/i,
loader: 'file-loader',
},
다시 빌드 해보자!
...
에러가 또 나왔다.
ERROR in ./src/style.scss
Module build failed (from ./node_modules/mini-css-extract-plugin/dist/loader.js):
Error: Automatic publicPath is not supported in this browser
publicPath를 내가 직접 지정해 줘야한다는데,,publicPath가 뭐지?
publicPath
경로 앞에 붙일 string을 의미한다. 예를들어서,
#page {
overflow: hidden;
.bg{
background: url('./assets/bg.png') no-repeat;
overflow:hidden;
}
이렇게 하고, webpack.config.js
를 아래와 같이 수정하고
{
test: /\.(scss|css)$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: 'abc'
}
},
"css-loader", "sass-loader"
]
},
build하면 이런식으로 된다.
.bg{
background:url(abc/f6d0d64669fe0481d16f73a173c63a4e.png)
}
파일명 앞에 abc
가 추가되었다.
근데 나는 url('./assets/bg.png')
이렇게 적었는데, .png
빼고 한글자도 같은게 없네? bg
는 뭐 파일이름이 webpack맘대로 바뀌었다고 치다손, ./assets
는 어디로 간걸까?
내 생각에는! file-loader가 ./assets/bg.png
을 읽어서 복사해가지고 dist
폴더에 f6d0d64669fe0481d16f73a173c63a4e.png
라는 이름으로 붙여넣기 한거다. 그리고 MiniCssExtractPlugin.loader
에서 지정한 publicPath
대로 앞에 abc
를 붙인거다.
publicPath
를 assets
으로 지정해서 다시 build해보자.
.bg {
background: url(./assets/f6d0d64669fe0481d16f73a173c63a4e.png)
}
예상대로 css파일에 주소는 publicPath가 적용되서 잘 바뀌었는데,

파일구조에,,,assets
폴더가 생성되지 않았다. 어떻게 하지?
name
rules: [
{
test: /\.(png|jpe?g|gif)$/i,
loader: 'file-loader',
options: {
name: 'assets/[contenthash].[ext]'
}
},
위처럼 하면 된다!. 알아서 assets
폴더를 만들어준다!
결과물
webpack.config.js
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const path = require('path');
const join = path.join;
const resolve = path.resolve;
module.exports = {
entry: join(__dirname, '/src/main.ts'),
devtool: 'source-map',
output: {
filename: "main.js",
path: join(__dirname, '/dist'),
},
module: {
rules: [
{
test: /\.(png|jpe?g|gif)$/i,
loader: 'file-loader',
options: {
name: 'assets/[contenthash].[ext]'
}
},
{
test: /\.(ts|tsx)$/,
exclude: /node_modules/,
use: 'ts-loader'
},
{
test: /\.(scss|css)$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: ''
}
},
"css-loader", "sass-loader"]
},
]
},
plugins: [
new MiniCssExtractPlugin({
filename: "style.css",
}),
new HtmlWebpackPlugin({
template: join(__dirname, '/src/index.html')
}),
new CleanWebpackPlugin({
cleanAfterEveryBuildPatterns: ['dist']
}),
],
resolve: {
extensions: ['.js', '.ts', '.json', 'scss']
}
};
파일구조

assets폴더가 생성되었고, 그 안에 파일이 잘 들어가있다.
style.scss
.bg{
background: url('./assets/bg.png') no-repeat;
overflow:hidden;
}
style.css(빌드후 생성된 파일)
.bg {
background: url(assets/f6d0d64669fe0481d16f73a173c63a4e.png)
}
브라우저에서 이미지를 잘 읽었는가?

잘 읽었다!