webpack的使用

# 什么是webpack?*

问题:为什么在 vue 中使用 npm run build 命令就可以把开发环境中的文件进行合并?

答案:无论是 vue 还是 react、angular,使用 cli 创建出来的项目,都自动的把结构做好了,内部的 webpack 也都配置好了,项目开发完毕后,只需要执行 build 命令,就能够把 src 下的文件进行打包,这个打包功能都是由 webpack 完成的,这个配置无需我们自己操作,vue、react、angular 内部已经整合完毕,只需要直接使用命令即可。

**如果想手动的一步一步的配置 webpack,那么可以根据下面的文档进行操作。**

webpack是资源加载/打包工具

```

project1/

    src/

    dist/

```

说白了,就是把开发环境src目录中的文件,打包到生产环境dist目录下。

- 在安装一个要打包到生产环境的安装包时,应使用 npm i -S,完整写法为 npm install --save lodash

- 如果安装一个用于开发环境的安装包,应使用 npm i -D,完整写法为 npm install --save-dev lodash

> 打包指把src下那些碎片化的文件,合并到一起,生成到dist下。

> 部署指把dist目录当成网站根目录,供别人访问。

# 如何使用webpack?

全局安装

```bash

npm i -g webpack webpack-cli

```

查看版本号

```bash

webpack -v      # 4.29.6

webpack-cli -v  # 3.3.0

```

创建项目目录

```bash

mkdir project1 && cd project1

```

初始化项目

```bash

npm init

```

>  npm init -y (-y参数的作用是创建package.json时都安装默认的来)

局部安装

```bash

npm i -D webpack webpack-cli

```

创建目录结构、文件和内容:

```

project1/

package.json

src/

index.js

```

src/index.js 中的代码:

- 在安装一个要打包到生产环境的安装包时,会打包到线上去并且在线上环境能用到的,应使用 npm i -S,完整写法为 npm install --save lodash

- 如果安装一个用于开发环境的安装包,只需要在开发的时候编译就好,线上并不需用的到,应使用 npm i -D,完整写法为 npm install --save-dev lodash

```javascript 

// lodash 是一个js工具库,用来操作 object、array、number... 更方便了

import _ from 'lodash'; // npm install --save lodash

function component(){

    var element = document.createElement('div')

    element.innerHTML = _.join(['Hello', 'webpack'], ' ')

    return element;

}

document.body.appendChild( component() )

```

创建目录结构、文件和内容:

```

project1/

package.json

dist/

index.html

```

dist/index.html 中的代码:

- main.js 文件目前还不存在

- 需要通过webpack把src/index.js文件及其依赖文件lodash打包到一起

```html

<!DOCTYPE html>

<html lang="en">

<head>

    <meta charset="UTF-8">

    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <meta http-equiv="X-UA-Compatible" content="ie=edge">

    <title>Document</title>

</head>

<body>


</body>

</html>       

<script src="main.js"></script>

```

在命令行中执行:

```bash

npx webpack

```

执行 npx webpack,会将我们的脚本作为入口起点,然后输出为 main.js

> Node 8.2+ 提供了 npx 命令,可以运行在初始安装的 webpack包(package)的webpack二进制文件

然后就可以浏览dist/index.html网页了

# 配置文件

在项目根目录下建立webpack.config.js文件

```

project1/

webpack.config.js

```

编写代码,配置打包内容。

```javascript

// 在 webpack 中使用 require 引入自带的path模块 (CommomJS规范)

const path = require('path')

module.exports = {

    entry: './src/index.js',

    output: {

        filename: 'index.js',

        path: path.resolve(__dirname, 'dist')

    }

}

```

> entry描述的是入口;output描述的是出口。

命令行执行:

```bash

npx webpack --config webpack.config.js

```

说明:根据配置页进行打包,入口为src/index.js,根据入口页的相关依赖,合并到dist/index.js中。

也可以直接执行:

```bash

webpack

```

两个命令是等效的

# NPM脚本

考虑到用 CLI 这种方法来运行本地的 webpack 不是特别方便,我们可以设置快捷方式。

在 package.json 文件的 scripts 对象中,增加 build 脚本,当执行 build 脚本时,实际执行的是 webpack 命令。

```

"scripts":{

    "abc" : "npx webpack --config webpack.config.js",

    "build": "webpack"

}

```

使用 npm run build 命令,代替之前使用的 webpack 命令。

```bash

npm run build  # npm run abc

```

# 资源管理

加载当前项目所用到的其他资源

- 加载 CSS

- 加载图片

- 加载字体

# 加载 CSS

下载在js中解析css的模块,我们要把js和css打包到一起。

```bash

npm install -D style-loader css-loader

```

webpack.config.js 配置规则

```javascript

module.exports = {

    entry: ......

    output: {} .....

    module: {

        rules:[

            { test:/\.css$/, use:['style-loader', 'css-loader'] }

        ]

    }

}

```

module.rules表示使用webpack打包模块时所定义的打包规则。

webpack打包时,如果碰到的是.css结尾的文件,使用style-loader和css-loader处理。

- style-loader:将 JS 字符串生成为 style 节点

- css-loader:将 CSS 转换为 CommonJS 模块

src/style.css

```css

.hello { color:red }

```

src/index.js

```javascript

import './style.css'

function component(){

    // ........

    element.classList.add('hello')

}

```

命令行中执行:

```bash

npm run build

```

如果想使用 scss 文件,需要安装

> npm config set sass-binary-site http://npm.taobao.org/mirrors/node-sass

```

npm install sass-loader node-sass --save-dev

```

然后规则中配置:

```

{ test:/\.scss$/, use:['style-loader', 'css-loader', 'sass-loader'] }

```

# 加载图片

CSS 和 JS 中的图片如何处理?

需要安装:

```

npm install --save-dev file-loader

```

然后在 webpack.config.js 页面中配置规则:

```

{ test:/\.(png|svg|jpg|gif)$/, use:['file-loader'] }

```

创建文件及编写代码

```

src/

    images/

        1.jpg

        2.jpg

index.js

import img from './images/1.jpg'

var myImg = new Image();

myImg.src = img;

document.body.appendChild( myImg );

style.scss

background: url(images/2.jpg)

```

命令行执行:

```

npm run build

```

两张图片会被复制到 dist 目录下面,网页能正常使用,如果想配置图片输出后的路径,可以:

```

use:[{

    loader:'file-loader',

    options:{

        name:'[name].[ext]',

        outputPath:'images'

    }

}]

```

# 加载字体

字体这种资源需要用到 file-loader 或 url-loader

```

npm i -D url-loader

```

规则配置:(二选一)

- file-loader会保存单独的字体文件

```

{ test: /\.(woff|woff2|eot|ttf|otf)$/, use: ['file-loader'] }

```

- url-loader会和js合并到一起

```

{ test: /\.(woff|woff2|eot|ttf|otf)$/, use: ['url-loader'] }

```

style.css 或 style.scss

```

@font-face{

    font-family: abc;

    src: url(./fonts/经典毛笔字体.ttf) format("truetype");

}

div{ font-family:"abc" }

```

命令行

```

npm run build

```

# 多入口多出口

PC端项目中可能有很多个入口,比如 index.html,比如 main.html 等,浏览器中都可以直接访问。

> 移动端项目SPA都是单页面应用,用一个入口就可以了,如果是传统的PC端,那么需要用到很多入口页面。

dist/index.html

```html

<script src="index.js"></script>

```

dist/main.html

```html

<script src="main.js"></script>

```

在浏览器中分别访问这两个文件,这两个文件分别依赖的js文件,都是独立的,这就是多入口多出口。

wepack.config.js

```javascript

entry:{

    index:'./src/index.js',

    main:'./src/main.js'

},

output:{

    filename:'[name].js',

    path:path.resolve(__dirname, 'dist')

}

```

entry描述的是入口,表示有两个入口 ,一个名字叫做index,一个名字叫做main。

output描述的是出口,filename描述的是打包后文件的名字,[name]是关键字表示entry入口文件名,path表示合并后文件所在位置。

命令行:

```bash

npm run build

```

就能够根据entry的配置打包出2个js文件了

# 插件

安装:

```bash

npm install --save-dev html-webpack-plugin

```

webpack.config.js

```javascript

const HtmlWebpackPlugin = require('html-webpack-plugin')

entry: { ... },

plugins: [ new HtmlWebpackPlugin({title:'标题栏内容'}) ],

output: { ... }

```

HtmlWebpackPlugin 的作用就是在 dist 目录下生成 index.html 文件,

我们现在的项目中存在 dist/index.html 所以命令执行后,会将之前的文件覆盖了,

如果项目中不存在 dist/index.html,那么 HtmlWebpackPlugin 也能够根据默认的配置把这个 index 文件创建出来。

# 清理dist目录

每次执行webpack编译时,最好先把之前的内容清理干净,然后重新生成。

```bash

npm install clean-webpack-plugin --save-dev

```

webpack.config.js

```javascript

const { CleanWebpackPlugin } = require('clean-webpack-plugin')

plugins:[

    new CleanWebpackPlugin(),

    new HtmlWebpackPlugin...

]

```

# 错误调试

webpack 是把很多个文件捆绑到一起,那么如果有段代码出错了,怎么定位错误?

src/print.js

把 console.log 改为 console.error 模拟一个错误出来,执行 npm run build 重新生成捆绑后的文件,浏览器运行。

浏览器的控制台中会报错,因为我们访问的是生产环境下的代码,所以报的是生产环境下的错误,所以不好定位错误。

webpack.config.js

```javascript

entry:{ ... },

devtool: 'inline-source-map'

```

加上 devtool 配置后,就能够定位到错误了,但要记得这仅仅是为了调试,生产时要关闭。

# 自动编译和自动刷新

每次修改文件后,都需要手动 npm run build 这太麻烦了,所以可以安装

```

npm install --save-dev webpack-dev-server

```

webpack.config.js

```javascript

devtool: 'inline-source-amp',

devServer: { contentBase: './dist' }    //把dist看作是一个根目录去运行

```

package.json

```javascript

"scripts":{

    "start" : "webpack-dev-server --open"

}

```

命令行运行

```bash

npm start

```

然后直接修改 src 下的文件,在浏览器中浏览 dist 下的文件,看效果。

# 别名

可以把长的文件名配置短的别名,这样描述依赖文件时会方便一些。

```javascript

output: {

    filename: '[name].bundle.js',

    path: path.resolve(__dirname, 'dist')

},

resolve:{

    alias: {

      '@': path.resolve('src'),

      '#': path.resolve('src/images'),

      'fa': path.resolve('src/fonts/font-awesome-4.7.0/css'),

    }

},

```

使用别名

```javascript

import printMe from '@/print.js'

import img from '#/1.jpg';

import 'fa/font-awesome.min.css'

```

> 不能用$当别名,修改webpack.config.js后要重新npm start

# 代理

解决跨域问题的一种方案

```javascript

devServer: {

    contentBase: './dist',    

    proxy:{

        "/api": {

            target: "http://www.wyyijiaqin.com",

            pathRewrite: { '^/api': '' },

            //secure: false,

            changeOrigin: true,

        }

    }

},

```

> 启动 devServer ,该代理才有作用。

# 打包时,代码是否压缩?

mode属性可以定义打包时代码是否压缩。

- development 不压缩代码

- production 压缩代码,默认

```javascript

output: {

    filename: '[name].bundle.js',

    path: path.resolve(__dirname, 'dist')

},

mode: "development"

```

# post-css

```bash

cnpm i postcss-loader -D

cnpm i autoprefixer -D  # 处理css浏览器兼容

```

这个模块是用来处理css兼容的,会自动给css加上浏览器前缀,如-ms- -webkit- 等

**style/index.css**

```css

span{

    background: red;

    color:white;

    display: flex;

    flex: 1;

    transform: translate(-50%, -50%)

}

```

**index.js**

```javascript

import './style/index.css';

```

**webpack.config.js**

```

{

    test: /\.css$/,

    use: ['style-loader', 'css-loader', {

        loader: 'postcss-loader',

        options:{

            plugins: [

                require('autoprefixer')("last 100 versions")

            ]

        }

    }]

}

```

> require('autoprefixer')("last 100 versions") 参数改了就会出错。

语义:如果碰到css文件,先用style-loader和css-loader 处理,然后用postcss-loader处理,使用require引入autoprefixer模块,处理css兼容

# 多个 config 文件入口

配置独立的 config 文件

比如我希望开发环境中,使用map,即出错时,能够看到错误内容,而生产环境下,出错时,不希望看到出错的具体内容,而且生产环境下的map还影响了文件的体积,所以应该去掉。

```bash

npm install --save-dev webpack-merge

```

**通用配置 common.js**

```javascript

const path = require('path');

module.exports = {

    entry: {

        index: './src/index.js'

    },

    output: {

        filename: '[name].js',

        path: path.resolve(__dirname, 'dist')

    }

};

```

**开发环境的配置 dev.js**

```

const merge = require('webpack-merge');

const common = require('./common.js');

module.exports = merge(common, {

    devtool: 'inline-source-map',

    devServer: {

        contentBase: './dist'

    }

});

```

**生产环境的配置 prod.js**

```

const merge = require('webpack-merge');

const common = require('./common.js');

module.exports = merge(common, {

});

```

**package.json**

```

"scripts": {

    "start": "webpack-dev-server --open --config dev.js",

    "build": "webpack --config prod.js"

}

```

执行 npm start 相当于开启了开发环境的服务,如果出错了,检查是不是某类文件类型的合并规则没有被定义。

执行 npm run build 表示根据开发环境中的文件,合并成生产环境下的文件。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,542评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,596评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,021评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,682评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,792评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,985评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,107评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,845评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,299评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,612评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,747评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,441评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,072评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,828评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,069评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,545评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,658评论 2 350

推荐阅读更多精彩内容