npm과 webpack 기반 빌드

Build tools for Frontend

기존 npm + bower + gulp 혹은 npm + ? + gulp 같이 쓰이다, yarn의 등장으로 npm 개선이 활발하고 해서 npm + gulp, npm + webpack 및 gulp 같은 쓰임이 대세인듯하다.



Webpack

WebPack은 ES6 코드로 핵심 모듈을 작성해 프론트 엔드 시스템을 빌드할 수 있다.

다음 핵심 개념을 이해할 필요가 있다.

  • Entry
    내부 의존성 그래프를 결과 빌드 시작에 사용하는 모듈을 가르킨다.
  • Output
  • Loaders
  • Plugins

entry

설정 파일에 하나 또는 그 이상의 entry 속성을 선언할 수 있다. entry points 문서를 참조.

1
2
3
module.exports = {
entry: "./path/to/my/entry/file.js",
};

Outout

output 속성은 번들을 생성하고 이름을 붙이는 것을 말한다.

1
2
3
4
5
6
7
8
9
const path = require("path");

module.exports = {
entry: "./path/to/my/entry/file.js",
output: {
path: path.resolve(__dirname, "dist"),
filename: "my-first-webpack.bundle.js",
},
};

이곳 output 속성에 대해 자세히 알 수 있다.

Loaders

loaders는 webpack은 자바스크립을 이해하지마 다른 처리를 할 수 있게 해준다. 기본적으로 로더는가 처리하는 파일은 모듈로 다뤄질 수 있다.

크게 로더는 설정에서 두 가지 목적을 갖는다.

  1. 어떤 파일이 이런 로더로 변형되는지 식별한다 (test 속성 사용)
  2. 의존성 그래프에 추가할 수 있게 파일을 변형한다 - 모듈이 된다 (use 속성 사용)

다음은 import, resolve.txt 파일이 있으면 모듈로 추가하기 전에 raw-loader 를 사용하라는 설정이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
const path = require("path");

const config = {
entry: "./path/to/my/entry/file.js",
output: {
path: path.resolve(__dirname, "dist"),
filename: "my-first-webpack.bundle.js",
},
module: {
rules: [{ test: /\.txt$/, use: "raw-loader" }],
},
};
module.exports = config;
  • rules 속성은 testuse 속성을 필요로 한다.

로더에 대해 더 자세히 알고 싶으면 Loaders를 참고하라.

Plugins

플러그인은 최적화, 최소화, 환경변수 등의 넓은 범위의 일을 할 수 있다. plugin interface는 강력한 힘을 줄 수 있다.

플러그인은 require() 구뭉을 사용한다. 그리고 new 연산자로 객체롤 plugins 배열에 추가해 준다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const HtmlWebpackPlugin = require("html-webpack-plugin"); //installed via npm
const webpack = require("webpack"); //to access built-in plugins
const path = require("path");

const config = {
entry: "./path/to/my/entry/file.js",
output: {
path: path.resolve(__dirname, "dist"),
filename: "my-first-webpack.bundle.js",
},
module: {
rules: [{ test: /\.txt$/, use: "raw-loader" }],
},
plugins: [
new webpack.optimize.UglifyJsPlugin(),
new HtmlWebpackPlugin({ template: "./src/index.html" }),
],
};
module.exports = config;


첫번째 프로젝트

여기 샘플 프로젝트 webpack-demo 폴더 구조는 보통 다음과 같다.

1
2
3
4
5
webpack-demo
|- package.json
+ |- index.html
+ |- /src
+ |- index.js

프로젝트 폴더에서 package.json 파일을 만들기 위해 초기화 한다.

1
2
3
mkdir webpack-demo
cd webpack-demo
git init

.gitignore

1
2
node_modules/**
build/**
1
2
git add .gitignore
git commit -m 'add gitignore'

src 파일

webpack getting started 샘플

src/index.js

1
2
3
4
5
6
7
8
9
function component() {
var element = document.createElement("div");

// Lodash, currently included via a script, is required for this line to work
element.innerHTML = _.join(["Hello", "webpack"], " ");

return element;
}
document.body.appendChild(component());

index.html

1
2
3
4
5
6
7
8
9
<html>
<head>
<title>Getting Started</title>
<script src="https://unpkg.com/lodash@4.16.6"></script>
</head>
<body>
<script src="./src/index.js"></script>
</body>
</html>

소스 추가

1
2
$ git add index.html src/
$ git commit -m 'add sample source'

npm init

1
npm init --yes

이렇게 생성된 package.json 은,

1
2
3
4
5
6
7
8
9
10
11
{
"name": "webpack-demo",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}
1
2
$ git add package.json
$ git commit -m 'initialize npm'

webpack 설치

typescript, 는 global 로 설치하자, 자주 쓰일 수 있다.

1
npm i -g -D typescript

개발용 Http server를 설치한다. 많이 사용되는 서버로 http-server, lite-server가 있다.

npm 으로 HTTP 서버를 띄워서 작업을 쉽게 할 수 있도록 http-server을 글로벌로 설치한다.

1
npm i -g -D http-server

결과를 브라우저에서 확인해 보자.

1
http-server -p 3000 -c-1 ./src"

webpack-dev-server”: “2.2.0” 를 설치하자

1
2
$ git add package.json
$ git commit -m 'add http-server'


### webpack

webpack은

1
2
npm i -D webpack
npm i -D webpack@<version>

로컬 설치시 node_modules/.bin/webpack 으로 실행할 수 있다.

package.json 에 webpack을 시작 명령으로 해준다.

1
2
3
"scripts": {
"start": "webpack --config webpack.config.js"
}

소스 디렉토리

src 폴더를 html, js 소스를 모두 포함하게 구성하자.

1
2
3
4
$ cd src
$ mkdir js
$ mv index.js js
$ mv ../index.html .

프로젝트 폴더는 아래 같이 구성된다.

1
2
3
4
5
6
webpack-demo
|- package.json
|- /src
|- /js
|- index.js
|- index.html
1
2
$ git add index.html src/
$ git commit -m 'all source at src'

외부 라이브러리

lodash 를 예로 들어 보자, lodash를 설치한다.

1
npm i lodash

ES2015의 import 구문을 이용해 외부 라이브러리를 들여온 후 webpack으로 빌드하면 하나의 최적화된 자바스크립 소스에 내장할 수 있다.

예를 들어 src/js/index.js 에 lodash 를 들여온다.

1
2
3
4
5
6
7
8
9
10
11
12
import _ from "lodash";

function component() {
var element = document.createElement("div");

// Lodash, now imported by this script
element.innerHTML = _.join(["Hello", "webpack"], " ");

return element;
}

document.body.appendChild(component());

역시 src/index.html 도 <script>로 들여온 lodash를 빌드 결과물 bundle.js 로 스크립트를 변경한다.

1
2
3
<body>
<script src="js/bundle.js"></script>
</body>

커밋한다.

1
2
$ git add package.json package-lock.json src/
git commit -m 'add lodash and commit to source'

bundle.js

node_modules/.bin/webpack 로 실행할 수 있으므로 src/js/index.js 를 진입점으로 해서 결과를 src/js/bundle.js 로 저장할 수 있다.

1
2
3
4
5
6
7
8
9
10
$ ./node_modules/.bin/webpack src/js/index.js src/js/bundle.js
Hash: ee3bf1d517f9a2f682ce
Version: webpack 3.8.1
Time: 2511ms
Asset Size Chunks Chunk Names
bundle.js 544 kB 0 [emitted] [big] main
[0] ./src/js/index.js 255 bytes {0} [built]
[2] (webpack)/buildin/global.js 488 bytes {0} [built]
[3] (webpack)/buildin/module.js 495 bytes {0} [built]
+ 1 hidden module

Webpack configuration

ES2015 표준의 import, export 구문은 기존 브라우저들이 지원되지 않는 경우가 많다. 그래서 ECMA6 를 ECMA5 로 전환 컴파일 하려면 Babel 같은 패키지를 사용한다.

이들 패키지지는 webpack 적재시스템을 통해 사용한다. 또 복잡한 프로젝트 요구를 위해서 설정 파일을 이용해 구성 가능하다. 이런 시나리오를 고려해 보자

  • webpack.config.js 에 소스 및 빌드 디렉토리가 명시되고
  • src/js/index.js 를 dist/assets/js/app.min.js 로 복사된다.
  • src/[html,js,css] 를 build/[html,assets/[js,css,images,ext]] 로 복사한다.

webpack configuration 파일은 webpack.config.js에 설정을 구성한다. 설정 구성 내용은 아래 같다.

1
2
3
4
5
6
7
const path = require("path");

module.exports = {
entry: "./src/*",
output: { filename: "", path: path.resolve(__dirname, "") },
plugins: [],
};

소스와 라이브러리 빌드 구성하기,

CopyWebpack plugin 은 파일 혹은 디렉토리를 빌드 디렉토리로 복사해 준다.

1
npm i -D copy-webpack-plugin

CopyWebpackPlugin은 객체를 생성해 사용한다.

new CopyWebpackPlugin([patterns], options)

  • pattern: { from: ‘source’, to: ‘dest’ }

webpack.config.js 을 프로젝트 루트에 저장하고 아래 같은 내용을 갖는다. webpack.config.js 파일에 플러그인을 구성한다.

1
2
3
4
5
6
7
8
9
10
11
const path = require("path");
var CopyWebpackPlugin = require("copy-webpack-plugin");

module.exports = {
entry: "./src/js/index.js",
output: {
filename: "js/bundle.js",
path: path.resolve(__dirname, "build/"),
},
plugins: [new CopyWebpackPlugin([{ from: "src/index.html" }])],
};

webpack 으로 빌드가 이루어지고 복사가 되는지 확인해 보자. webpack 을 시작하고 build 디렉토리를 확인해 보자.

1
$ ./node_modules/.bin/webpack --config webpack.config.js

웹 서버로 build 디렉토리를 시작해서 브라우저에서 확인해 보자.

npm 스크립트

npm으로 빌드와 테스트 서버 시작을 할 수 있도록 다음 같이 수정한다.

1
2
3
4
5
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "http-server -p 3000 -c-1 ./build",
"build": "NODE_ENV=developement node node_modules/.bin/webpack --config webpack.config.js"
},

이제 npm으로 build 스크립을 지시할 수 있다.
command and your parameters, e.g. npm run build – –colors.

1
npm run build

그리고 서버를 시작해 브라우저로 결과를 확인해 보자.

커밋한다.

1
$ git add package* webpack.config.js
"start": "node node_modules/.bin/webpack-dev-server --content-base app",
"test": "NODE_ENV=test karma start",

"build": "NODE_ENV=production node node_modules/.bin/webpack --config webpack.config.js && cp src/index.html dist/index.html",

file-loader plugin

file-loader

npm i -D webpack-stream

Babel

1
2
npm i -D babel-core babel-loader babel-preset-latest
npm install babel-core babel-loader babel-preset-es2015

참조

https://pawelgrzybek.com/using-webpack-with-gulpjs/

Author

Gangtai Goh

Posted on

2017-09-10

Updated on

2023-01-14

Licensed under

댓글