Posts webpack-html과 scss 그리고 code spliting 적용하기
Post
Cancel

webpack-html과 scss 그리고 code spliting 적용하기

webpack으로 scss와 code spliting, 이미지 가져오기를 적용해보았다. 가장 문제가 되었던 것이 webpack-dev-server와 build한 파일의 publicPath가 일치하지 않은 것이었다.

production mode일 때, publicPath에 파일들이 위치할 서버 상의 경로를 넣어주면 빌드 시에는 번들한 파일 이름 앞에 해당 설정값이 포함되어 html에 script 태그로 자동 입력된다. 나의 경우 로컬의 파일구조 /webpack/dist/를 설정값에 적어주면 html에 /webpack/dist/(번들된 파일)로 자동으로 입력되었다.

1
2
3
4
<script
  defer="defer"
  src="/webpack/dist/vendor.0ef3ea92ffc39d3f0fbb.js"
></script>


그러나 development mode일 경우, webpack-dev-server로 가상의 서버를 띄웠을 때는 /로 설정해야 웹팩 데브 서버가 번들한 결과물이 위치하는 경로를 제대로 읽어낼 수 있었다.

1
<script defer="defer" src="/vendor.0ef3ea92ffc39d3f0fbb.js"></script>


webpack/webpack.config.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const { WebpackManifestPlugin } = require('webpack-manifest-plugin');

module.exports = (env, options) => {
  const prod = options.mode === 'production';
  console.log(prod);
  const config = {
    mode: prod ? 'production' : 'development',
    devtool: prod ? 'eval' : 'hidden-source-map',
    resolve: {
      extensions: ['.js'],
    },
    entry: {
      index: ['./src/index.js'],
    },
    output: {
      path: path.join(__dirname, './dist'), //output으로 나올 파일이 저장될 경로
      publicPath: prod ? '/webpack/dist/' : '/', //파일들이 위치할 서버 상의 경로(빌드 시 내 로컬 파일 구조)
      filename: '[name].[chunkhash].js', //청크별로 해시값이 부여
    },
    plugins: [
      new CleanWebpackPlugin(), //빌드할 때 전에 빌드할 때 미리 만들어져있는 파일이 있다면 삭제하기(기본적으로 변경되는 부분만 바뀐다, 단 npm run dev를 하면 전체 삭제됨)
      new HtmlWebpackPlugin({
        template: './src/index.html', //정의되어있는 기본 template을 기준으로 번들링 시에 새로운 html 파일을 생성해 준다(js, css에 수정사항이 있을 시)
      }),
      new MiniCssExtractPlugin({
        filename: '[name].[contenthash].css',
        chunkFilename: '[id].[contenthash].css',
      }), //여러 css 파일을 하나의 파일로 묶어서 번들링함
      new webpack.LoaderOptionsPlugin({
        minimize: true,
      }), //loader들의 옵션을 설정할 수 있다
      new WebpackManifestPlugin(), //manifest파일을 자동으로 생성한다, 별다른 설정없이도 빌드할 때마다 manifest의 파일경로(src)가 바뀌는데 이 바뀌는 경로들이 자동으로 html파일에 적용된다.
    ],
    module: {
      rules: [
        {
          test: /\.scss$/,
          use: [
            prod ? MiniCssExtractPlugin.loader : 'style-loader',
            'css-loader',
            'sass-loader',
          ],
        },
        {
          test: /\.js?$/,
          loader: 'babel-loader',
          options: {
            plugins: ['@babel/plugin-syntax-dynamic-import'], //코드 스플리팅을 적용한다
            presets: [
              [
                '@babel/preset-env',
                {
                  modules: false,
                  targets: '> 0.25%, not dead',
                  useBuiltIns: 'entry',
                  corejs: '3.0.0',
                },
              ],
            ],
          },
          exclude: ['/node_modules'],
        },
        {
          test: /\.(ico|png|jpg|jpeg|gif|svg|woff|woff2|ttf|eot)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
          loader: 'url-loader',
          options: {
            name: '[hash].[ext]', //[hash]는 웹팩 빌드를 할 때마다 고유값이 설정됨
            limit: 10000,
            esModule: false,
          },
        },
      ],
    },
    devServer: {
      historyApiFallback: true,
      publicPath: '/', // 웹팩 데브 서버가 번들한 결과물이 위치하는 경로(보통 output에 적어주는 publicPath와 동일한 위치를 표시),
      contentBase: path.join(__dirname, './dist'), //콘텐츠를 제공할 경로지정(정적파일을 제공하려는 경우에만 필요),
    },
    optimization: {
      minimize: true,
      splitChunks: {
        cacheGroups: {
          vendor: {
            // 청크들간 공통적으로 사용하는 모듈들을 모아둔 것
            chunks: 'initial',
            name: 'vendor',
            enforce: true,
          },
        },
      },
      concatenateModules: true,
    },
  };

  return config;
};


webpack/src/index.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import './style/main.scss';
import 'core-js/stable';
import 'regenerator-runtime/runtime';
//다음과 같이 import하면 웹팩에서 알아서 해당 코드가 필요할 때마다 비동기적으로 로딩해준다, import한 값은 Promise객체이다
import(/* webpackChunkName: "module" */ './module')
  .then(function (res) {
    const p = document.createElement('p');
    p.textContent = res.default;
    document.body.append(p);
  })
  .catch(function (err) {
    console.error('module error', err);
  });

const div = document.createElement('div');
document.body.append(div);

결과물은 다음과 같다.

webpack/dist/index.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" lang="ko" />
    <title>hello</title>
    <script
      defer="defer"
      src="/webpack/dist/vendor.0ef3ea92ffc39d3f0fbb.js"
    ></script>
    <script
      defer="defer"
      src="/webpack/dist/index.f41f95a8ac593bbf808a.js"
    ></script>
    <link
      href="/webpack/dist/vendor.30ab4e262a68d4200550.css"
      rel="stylesheet"
    />
  </head>
  <body>
    <div>hello</div>
  </body>
</html>

webpack_html

전체 폴더 구조는 깃헙에 있습니다

출처:

[BuildSystem][ModuleBundler][Webpack]sass(scss)를 css로 바꾸기(3)

Webpack 완전정복하기!!

zeroCho blog: Webpack

This post is licensed under CC BY 4.0 by the author.

Algorithm-삽입 정렬

github.io에서 velog로 블로그 이사합니다.

Comments powered by Disqus.