阅读 74

二、Webpack配置应用

1、多页应用

// webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
  mode: 'development',
  // 多入口
  entry: {
    page1: './src/index1.js',
    page2: './src/index2.js'
  },
  output: {
    filename: '[name].js',
    path: path.resolve(__dirname, 'dist')
  },
  plugins: [
    new HtmlWebpackPlugin({ // 有两个页面,就需要 new 两次
      template: './src/index1.html',
      filename: 'page_1.html',
      chunks: ['page1'] // [代码块] 引入对应的js文件,这个文件名是 entry 中的命名
    }),
    new HtmlWebpackPlugin({
      template: './src/index2.html',
      filename: 'page_2.html',
      chunks: ['page1', 'page2']
    })
  ]
}
复制代码

项目目录:

image.png

2、source-map 源码映射

yarn add @babel/core @babel/preset-env babel-loader -D
复制代码

1. source-map

源码映射,会单独生成一个sourcemap文件,代码出错会标识代码报错的列和行

2. eval-source-map

不会产生单独的文件,但是会显示报错的行和列

3. cheap-module-source-map

不会产生标识代码报错的列和行,但是是一个单独的映射文件。产生文件可以保留,用于调试,找到第几行

4. cheap-module-eval-source-map

如果有报错提示,试试使用这个:eval-cheap-module-source-map

不会产生映射文件,也不会显示对应列,集成在打包后的文件中

// webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
    mode: 'production',
    entry: {
        index: './src/index.js'
    },
    output: {
        filename: '[name].js',
        path: path.resolve(__dirname, 'dist')
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: './src/index.html',
            filename: 'index.html'
        })
    ],
    // 第一种:源码映射,会单独生成一个sourcemap文件,代码出错会标识代码报错的列和行
    // devtool: 'source-map', // 增加映射文件,可以便于调试源码
    // 第二种:不会产生单独的文件,但是会显示报错的行和列
    // devtool: 'eval-source-map',
    // 第三种:不会产生标识代码报错的列,但是是一个单独的映射文件。产生文件可以保留,用于调试,找到第几行
    // devtool: 'cheap-module-source-map',
    // 第四种:不会产生映射文件,也不会显示对应列,集成在打包后的文件中
    devtool: 'eval-cheap-module-source-map',
    module: {
        rules: [
            {
                test: /\.js$/,
                use: {
                    loader: 'babel-loader',
                    options: {
                        presets: ['@babel/preset-env']
                    }
                }
            }
        ]
    }
}
复制代码

3、Watch 实时打包

实时打包,不需要每次修改代码后手动打包。

// webpack.config.js
module.exports = {
    // ...
    watch: true,
    watchOptions: { // 监控的选项
        poll: 1000, // 每秒问我们1000次是否需要打包
        aggregateTimeout: 500, // 防抖:500ms内一直操作,500ms后还没有操作就打包
        ignored: /node_modules/ // 不需要监控哪个文件
    }
    // ...
}
复制代码

4. Webapck插件的应用

1. clean-webpack-plugin 打包前先清空当前打包目录下的文件

参考链接:clean-webpack-plugin

// webpack.config.js
const { CleanWebpackPlugin } = require('clean-webpack-plugin');

module.exports = {
    // ...
    plugins: [
        new CleanWebpackPlugin()
    ],
    // ...
}
复制代码

2.copy-webpack-plugin 拷贝一些静态文件到打包目录下

参考链接:copy-webpack-plugin

通常会用于拷贝一些静态文件到打包目录下

// webpack.config.js
const CopyWebpackPlugin = require('copy-webpack-plugin');
module.exports = {
    // ...
    plugins: [
        new CopyWebpackPlugin({
            patterns: [
                { from: './doc', to: './doc'}
            ]
        })
    ],
    // ...
}
复制代码

3. bannerPlugin 版权声明

这是Webpack内置的插件

参考链接:bannerPlugin

// webpack.config.js
const Webpack = require('webpack');
module.exports = {
    // ...
    plugins: [
        new Webpack.BannerPlugin('Made my Hanshin')
    ]
    // ...
}
复制代码

5、跨域处理

// webpack.config.js
module.exports = {
    // ...
    devServer: {
        proxy: {
            // '/api': 'http://localhost:3000'
            '/api': {
                target: 'http://localhost:3000',
                pathRewrite: {
                    '/api': ''
                }
            }
        }
    }
    // ...
}
复制代码

6、MOCK数据,仅前端模拟数据

// webpack.config.js
module.exports = {
    // ...
    devServer: {
        before(app) {
            app.get('/api', (req, res) => {
                res.json({
                    key: 'hello world'
                })
            })
        }
    }
    // ...
}
复制代码

7、有服务端,在服务端中启动webpack,端口使用服务端端口

前后端启动在一起,如下,访问 localhost:3000即可

node server.js 即可

// server.js
const express = require('express');
const app = express();

const webpack = require('webpack');
// 需要中间件
const middle = require('webpack-dev-middleware');
const config = require('./webpack.config');
const compiler = webpack(config);
app.use(middle(compiler));

app.get('/api', (req, res) => {
  res.json({
    key: 'hello world111'
  })
})

app.listen(3000);
复制代码

8、Webpack解析第三方包

1. 解析引用模块

解析的欧快可能都来源于第三方包。

commonJS 规范:先找当前目录下的 node_modules,找不到在往上找。

所以我们可以配置强制在当前目录找。

// webpack.config.js
module.exports = {
    // ...
    resolve: {
        modules: [path.resolve('node_modules')]
    }
    // ...
}
复制代码

2. 样式文件的引入,如bootatrap

  • 方案一:
// index.js
import 'bootstrap' // 只这样写不做配置是不会生效的,会默认去找js文件
import 'bootstrap/dist/css/bootstrap.css' // 这样写是生效的
复制代码

可以这样处理:

  • 方案二:
// index.js
import 'bootstrap'

// webpack.config.js
module.exports = {
    // ...
    resolve: {
        alias: { // 别名
            bootstrap: 'bootstrap/dist/css/bootstrap.css'
        }
    }
    // ...
}
复制代码
  • 方案三:
// index.js
import 'bootstrap'

// webpack.config.js
module.exports = {
    // ...
    resolve: {
        mainFields: ['style', 'main'] // 主入口的字段,从左往右找,找不到再往右找
    }
    // ...
}
复制代码

这个 mainFields 对应 bootstrap 下面的 package.json 中的style 、 main 这些key。

mainFiles

// webpack.config.js
module.exports = {
    // ...
    resolve: {
        // 入口文件名,未指定默认找index.js。如果指定了,从左往右找,直到找到为止
        mainFiles: ['index1', 'index']
    }
    // ...
}
复制代码

3. css等文件的引入

  • 方案一:
// index.js
import './style.css'
复制代码
  • 方案二:

为了方便,可以这样引入:

// index.js
import './style'

// webpack.config.js
module.exports = {
    // ...
    resolve: {
        // import文件的时候如果没写后缀,自动补充后缀,从左往右,直到找到这个文件为止
        extensions: ['.js', '.css', '.json']
    }
    // ...
}
复制代码

9、Webapck 定义环境变量及不同环境的处理

下面这样是错误的,会提示 dev 未定义:

// index.js
console.log(DEV);

// webpack.config.js

const Webpack = require('webpack');

module.exports = {
    // ...
    plugins: [
        new Webpack.DefinePlugin({
            DEV: 'dev'
        })
    ]
    // ...
}
复制代码

可以这样处理:

// index.js
console.log(DEV); // 'dev'
console.log(PRO); // 'PRO'
console.log(NUM); // 2
console.log(TYPE); // true

// webpack.config.js
const Webpack = require('webpack');

module.exports = {
    // ...
    plugins: [
        new Webpack.DefinePlugin({
            DEV: "'dev'",
            PRO: JSON.stringify('PRO'),
            NUM: '1+1',
        	TYPE: 'true'
        })
    ]
    // ...
}
复制代码

我们可以通过不同文件来区分不同的环境:

新建各自的配置文件 webpack.base.jswebpack.pro.jswebpack.dev.js

安装插件:yarn add webpack-merge -D

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

module.exports = {
    entry: {
        index: './src/index.js'
    },
    output: {
        filename: '[name].js',
        path: path.resolve(__dirname, 'dist')
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: './src/index.html',
            filename: 'index.html'
        }),
        new CleanWebpackPlugin()
    ],
    module: {
        rules: [
            {
                test: /\.js$/,
                use: {
                    loader: 'babel-loader',
                    options: {
                        presets: ['@babel/preset-env']
                    }
                }
            }
        ]
    }
}
复制代码
// webpack.dev.js
const { merge } = require('webpack-merge');
const base = require('./webpack.base.js');
const Webpack = require('webpack');

module.exports = merge(base, {
    mode: 'development',
    plugins: [
        new Webpack.DefinePlugin({
            ENV: JSON.stringify('development')
        })
    ]
})

复制代码
// webpack.pro.js
const { merge } = require('webpack-merge');
const base = require('./webpack.base.js');
const Webpack = require('webpack');

module.exports = merge(base, {
    mode: 'production',
    plugins: [
        new Webpack.DefinePlugin({
            ENV: JSON.stringify('production')
        })
    ]
})
复制代码
文章分类
前端
文章标签