webpack4.0 的搭建

了解webpack

1 webpack

  • webpack是模块打包器
  • 所有资源文件会当做模块处理
  • 它将根据模块的依赖关系进行静态分析,生成对应的静态资源

2 核心概念

  • Entry: 入口文件指示webpack使用了哪些模块,来作为构建其内部依
    赖图的开始。
  • Output:告诉 webpack 在哪里输出它所创建的打包文件,以及如何
    命名这些文件。
  • Loader:让 webpack 能够去处理那些非 JavaScript 文件(webpack
    自身只能解析 JavaScript)。
  • Plugins:插件则可以用于执行范围更广的任务。插件的范围包括,
    从打包优化和压缩,一直到重新定义环境中的变量等。
  • Mode:模式,有生产模式production和开发模式development。

前期准备

1 初始化项目
执行以下命令:

mkdir webpack-demo
cd webpack-demo
npm init -y
npm install webpack webpack-cli --save-dev

2 创建目录及文件

main.js为入口文件,src为开发中具体代码。

webpack-demo
├── dist
│   └── index.html
├── main.js
├── package-lock.json
├── package.json
├── src
│   └── page
│       └── index.js

3 安装cross-env 可配置多个环境变量

npm install cross-env --save-dev

4 修改package.json

修改安装包是私有的(private),并且移除 main 入口。防止发布你的代码。

{
   "name": "webpack-demo",
   "version": "1.0.0",
   "description": "",
  + "private": true,
  - "main": "index.js",
   "scripts": {
      -"test": "echo \"Error: no test specified\" && exit 1",
      +"dev": "cross-env NODE_ENV=development webpack --config build/webpack.config.js",
      +"build": "cross-env NODE_EAN=production webpack"
  },
   "keywords": [],
   "author": "",
   "license": "ISC",
   "devDependencies": {
     "webpack": "^4.43.0",
     "webpack-cli": "^3.3.12"
   }
}

5 增加webpack配置文件 webpack.config.js

创建webpack.config.js,配置webpack。

webpack-demo
├── build
│   └── webpack.config.js
├── dist
│   └── index.html
├── main.js
├── package-lock.json
├── package.json
├── src
│   └── page
│       └── index.js

webpack.config.js配置如下:

const path = require('path');
module.exports = {
    mode: 'development',
    entry: './main.js',
    output: {
        filename: 'bundle.js',
        path: path.resolve(__dirname, '..', 'dist')
    }
};

6 入口文件main.js编写代码

document.write('Hi~~~');
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>webpack</title>
    <script src="bundle.js"></script>
</head>
<body>

</body>
</html>

7 测试打包

npm run dev

打包结果如下:

Hash: 6c2d1c4815da9f363f24
Version: webpack 4.43.0
Time: 82ms
Built at: 2020-06-30 4:31:46 PM
    Asset      Size  Chunks             Chunk Names
bundle.js  3.76 KiB    main  [emitted]  main
Entrypoint main = bundle.js
[./main.js] 24 bytes {main} [built]

8 浏览器运行

浏览器运行index.html,显示“Hi~~~”。

分离生产环境和生产环境

1 拆分文件

修改webpack.config.js为webpack.common.js
增加webpack.dev.js
增加webpack.prod.js

webpack-demo
├── build
│   ├── webpack.common.js
│   ├── webpack.dev.js
│   └── webpack.prod.js
├── main.js
├── package-lock.json
├── package.json
├── src
│   └── page
│       └── index.js

2 修改package.json的配置

"scripts": {
    "dev": "cross-env NODE_ENV=development webpack --config build/webpack.dev.js",
    "build": "cross-env NODE_ENN=production webpack --config build/webpack.prod.js"
  }

3 编译前自动清空dist目录、从html模板自动生成最终html、安装webpack-merge插件进行拆分

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

4 修改配置文件

webpack.common.js修改如下:

const path = require('path');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
    entry: './main.js',
    output: {
        filename: 'bundle.js',
        path: path.resolve(__dirname, '..', 'dist')
    },
    plugins: [
        new CleanWebpackPlugin(),
        new HtmlWebpackPlugin({
            filename: path.resolve(__dirname, '..', 'dist/index.html'),
            template: 'index.html'
        })
    ]
};

webpack.dev.js文件修改如下:

const common = require('./webpack.common');
const merge  = require('webpack-merge');

module.exports = merge(common, {
    mode: 'development'
});

webpack.prod.js文件修改如下:

const common = require('./webpack.common');
const merge  = require('webpack-merge');

module.exports = merge(common, {
    mode: 'production'
});

5 增加html文件作为模板

文件目录以及html文件内容修改如下:

webpack-demo
├── build
│   ├── webpack.common.js
│   ├── webpack.dev.js
│   └── webpack.prod.js
├── dist
│   ├── bundle.js
│   └── index.html
+├── index.html
├── main.js
├── package-lock.json
├── package.json
├── src
│   └── page
│       └── index.js
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>webpack</title>
</head>
<body>

</body>
</html>

6 测试打包

执行 npm run dev 可以看到dist目录下打包文件以及自动生成的index.html文件,浏览器打开dist下index.html文件,可以看到输出Hi~~~。

搭建开发环境的热更新服务器

搭建开发环境下基于node.js的服务器,实现在修改代码时不用刷新即可自动热更新页面。安装 npm install webpack-dev-server --save-dev,
修改package.json文件,如下:

"scripts": {
    "dev": "cross-env NODE_ENV=development webpack --config build/webpack.dev.js",
    "build": "cross-env NODE_ENV=production webpack --config build/webpack.prod.js",
   + "server": "cross-env NODE_ENV=development webpack-dev-server --open --config build/webpack.dev.js"
  },

修改webpack.dev.js文件如下:

const common = require('./webpack.common');
const merge  = require('webpack-merge');

module.exports = merge(common, {
    mode: 'development',
    devServer: {
        contentBase: './dist',
        port: 8080,
        hot: true
    }
});

执行npm run server,会在本地启动一个nodejs的web服务,浏览器会自动打开http://localhost:8080/。输出内容 Hi~~~。这时修改main.js文件,页面会自动更新。

7 使用source-map追踪源代码错误

在编译生成的dist目录中,js代码已被重新混淆,如果出现错误,无法将错误正确定位到原始代码的对应位置,这样不方便调试生成环境的代码。如果需要精确调试生产环境代码,可通过source-map实现。
inline-source-map: 将source map 转换为 DataUrl 后添加到页面的js中,生成的js文件较大(不推荐)。
source-map: 生成对应的map文件,js较小(推荐)。
修改webpack.prod.js如下:

const common = require('./webpack.common');
const merge  = require('webpack-merge');

module.exports = merge(common, {
    mode: 'production',
    devtool: 'source-map'
});

8 兼容ES6

npm install babel-loader @babel/core @babel/preset-env --save-dev
webpack.common.js文件增加babel-loader,如下:

output: ...
module: {
        rules: [
            {
                test: /\.(js|jsx)$/,
                exclude: /(node_modules|bower_components)/,
                use: {
                    loader: 'babel-loader',
                    options: {
                        presets: ['@babel/preset-env']
                    }
                }
            }
        ]
    },
    plugins: ...

9 加载css和less

npm install style-loader css-loader --save-dev
npm install less-loader less --save-dev
新加入index.css文件,内容如下:

webpack-demo
├── build
│   ├── webpack.common.js
│   ├── webpack.dev.js
│   └── webpack.prod.js
├── dist
├── index.html
├── main.js
├── package-lock.json
├── package.json
├── src
+│   ├── css
+│   │   └── index.less
│   └── page
│       └── index.js

index.less文件加入以下代码:

body{
  background: gainsboro;
}

webpack.common.js增加loader:

module: {
        rules: [
            {
                test: /\.(js|jsx)$/,
                exclude: /(node_modules|bower_components)/,
                use: {
                    loader: 'babel-loader',
                    options: {
                        presets: ['@babel/preset-env']
                    }
                }
            },
            {
                test: /\.css$/,
                use: [
                    'style-loader',
                    'css-loader'
                ]
            },
            {
                test: /\.less$/,
                use: [
                    'style-loader',
                    'css-loader',
                    'less-loader'
                ]
            },
        ]
    }

执行npm run server 就会看见背景颜色为灰色,样式代码会直接打包插入到html文件中,控制台查看元素,可以看到以下代码。

<style>
    body {
       background: gainsboro;
    }
</style>

10 分离样式到css文件

上面打包之后的样式并没有用link方式引入,现在我们想把样式通过link方式引入。npm install mini-css-extract-plugin --save-dev,修改webpack.common.js文件如下:

module: {
        rules: [
            ...
            {
                test: /\.css$/,
                use: [
                    // 'style-loader',
                    // 将原来的style-loader替换,可以通过link方式引入
                    MiniCssExtractPlugin.loader,
                    'css-loader'
                ]
            },
            {
                test: /\.less$/,
                use: [
                    // 'style-loader',
                    MiniCssExtractPlugin.loader,
                    'css-loader',
                    'less-loader'
                ]
            },
        ]
    },
    plugins: [
        ...
        new MiniCssExtractPlugin({
            filename: path.posix.join('css/[name].css'),
            chunkFilename: path.posix.join('css/[name].[chunkhash].css')
        })
    ]

执行 npm run dev 可以看到打包文件dist下有css文件夹 mian.css。
控制台可以看到引入方式为link引入:

<link href="css/main.css" rel="stylesheet">

11 还可以加入其它loader

例如 图片、字体等。

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