Entry

Entry 用来指定webpack打包的入口
  • 单入口:entry是一个字符串
module.exports = {
    entry: './path/entry/file.js'
}
  • 多入口: entry是一个对象
module.exports = {
    entry: {
        app: './src/app.js',
        search: './src/search.js'
    }
}

Output

Output 用来告诉webpack如何将编译后的文件输出到磁盘
  • 单入口
module.exports = {
    entry: './path/entry/file.js',
    output: {
        filename: "bundle.js",
        path: path.join(__dirname, 'dist')
    }
}
  • 多入口
module.exports = {
    entry: {
        app: './src/app.js',
        search: './src/search.js'
    },
    output: {
        filename: '[name].js',
        path: path.join(__dirname, 'dist')
    }
}

loaders

webpack 默认只支持JS和JSON两种文件类型,通过Loaders去支持其它文件类型并且把它们转成有效模块

常见loader:

属性 说明
babel-loader 转换ES6、ES7等JS新特性语法
css-loader 支持.css文件的加载和解析
less-loader 将less文件转换成css
ts-loader 将ts转换成js
file-loader 进行图片、字体等的打包
raw-loader 将文件以字符串的形式导入
thread-loader 多进程打包JS和CSS

用法:

module.exports = {
    entry: {
        app: './src/app.js',
    },
    output: {
        filename: 'bundle.js',
    },
    module: {
        rules: [
            { test: '\.txt$',use: 'raw-loader' }
        ]
    }
}

plugins

插件用于bundle文件的优化,资源管理和环境变量的注入

常见plugins:

属性 说明
SplitChunksPlugin 将chunks相同的模块代码提取成公共的js
CleanWebpackPlugin 清理构建目录
MiniCssExtractPlugin 将CSS提取到单独的文件中
CopyWebpackPlugin 将文件或文件夹拷贝到构建的输出目录
HtmlWebpackPlugin 创建html文件去承载输出的bundle
UglifyjsWebpackPlugin 压缩js
ZipWebpackPlugin 将打包出来的资源生成一个zip包

用法:

module.exports = {
    entry: {
        app: './src/app.js',
    },
    output: {
        filename: 'bundle.js',
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: './src/index.html'
        })
    ]
}

mode

mode用来指定当前构建环境是:production、development和none,默认为production
选项 说明
development 设置process.env.NODE_ENV的值为development,
开启NamedChunksPlugin和NamedModulesPlugin
production 设置设置process.env.NODE_ENV的值为production
none 不开启

文件监听

发现源码发送变化时,自动构建出新的输出文件

轮询判断文件的最后编译时间是否变化

某个文件发生了变化,并不会立即告诉监听者,而是缓存起来,等aggregateTimeout
module.export = {
    //默认false
    watch: true,
    watchOptions: {
        // 默认为空,不监听的文件,支持正则匹配
        ignored: /node_modules/,
        // 监听到变化后等300ms再去执行,默认300ms
        aggregateTimeout: 300,
        // 轮询时间1000ms
        poll: 1000
    }
}

热更新

webpack-dev-server

// package.json
{
    "scpirt": {
        "dev": "webpack-dev-server --open"
    }
}
// webpack.config.js
module.export = {
    plugins: [
        // hot:true 会自动引入
        new webpack.HotModuleReplacementPlugin()
    ],
    devServer: {
        contentBase: './dist',
        hot: true,
        // hotOnly:true // 热更新失败不自动刷新
    }
}

// js代码实现热更新需要添加以下代码
if (module.hot) {
  module.hot.accept()
}

webpack-dev-middleware

原理

  • Webapck Compile: 将JS编译成Bundle
  • HMR Server: 将热更新的文件输出给HMR Runtime。是服务端,用来将变化的 js 模块通过 websocket 的消息通知给浏览器端。
  • HMR Runtime: 会被注入到浏览器,更新文件的变化。是浏览器端,用于接受 HMR Server 传递的模块数据,浏览器端可以看到 .hot-update.json 的文件过来。
  • Bundle server: 提供文件在浏览器的访问。
  • bundle.js: 构建输出的文件

文件指纹

Hash: 和整个项目的构建相关,只要文件修改,整个项目构建的hash值就会修改

Chunkhash: 和webpack打包的chunk有关,不同的entry会生成不通过的chunkhash值
Contenthash: 根据文件内容来定义hash,文件内容不变,则contenthash不变
//通常js使用chunkhash
output: {
    path: path.join(__dirname, 'dist'),
    filename: '[name]_[contentHash:8].js'
},

//css使用contenthash
new MiniCssExtractPlugin({
    filename: '[name]_[contentHash:8].css'
}),

//图片通常使用hash
{
    test: /\.(png|svg|jpg|gif)$/,
    use: [{
        loader: 'file-loader',
        options: {
            name: 'img/[name][hash:8].[ext]'
        }
    }]
},

代码压缩

js压缩

内置了uglifyjs-webpack-plugin

css压缩

optimize-css-assets-webpack-plugin

new OptimizeCssAssetsWebpackPlugin({
    assetNameRegExp: /\.css$/g,
    cssProcessor: require('cssnano')
}),

html压缩

使用html-webapck-plugin,设置压缩参数

new HtmlWebpackPlugin({
    template: path.join(__dirname, 'src/index.html'),
    filename: 'index.html',
    chunks: '[index]',
    inject: true,
    minify: {
        html5: true,
        collapseWhitespace: true,
        preserveLineBreaks: false,
        minifyCSS: true,
        minifyJS: true,
        removeComments: false
    }
}),

自动清理目录

使用clean-webpack-plugin,默认会删除output指定的输出目录
const { CleanWebpackPlugin } = require('clean-webpack-plugin');

new CleanWebpackPlugin()

自动补全css3前缀

postcss-loader和autoprefixer

px自动转换成rem

px2rem-loader,可结合lib-flexible自动修改根元素font-size(最大为54px)
{
    test: /\.less$/,
    use: [
        MiniCssExtractPlugin.loader,
        'css-loader',
        {
            loader: 'postcss-loader',
            options: {
                plugins: () => [
                    require('autoprefixer')({
                        overrideBrowserslist: ['> 0.15% in CN']
                    })
                ]
            }
        },
        {
            loader: 'px2rem-loader',
            options: {
                // 1rem = 75px
                remUnit: 75,
                // 小数点位数
                remPrecision: 8 
            }
        },
        'less-loader'
    ]
},

source map

通过source map定位到源代码,开发环境开启,线上环境关闭

关键字

  • eval: 使用eval包裹模块代码
  • source map: 产生.map文件
  • cheap: 不包含列信息
  • inline: 将.map作为DataUrl嵌入,不单独生成.map文件
  • module: 包含loader的sourcemap

类型

  • (none)
  • eval
  • cheap-eval-source-map
  • cheap-module-eval-source-map
  • eval-source-map
  • cheap-source-map
  • cheap-module-source-map
  • inline-cheap-source-map
  • inline-cheap-module-source-map
  • source-map
  • inline-source-map
  • hidden-source-map
  • nosources-source-map

提取页面公共资源

利用webpack4内置的SplitChunksPlugin进行公共脚本分离
chunks参数说明:

  • async 异步导入的库进行分离(默认)
  • initial 同步导入的库进行分离
  • all 所有导入的库进行分离(推荐)

基础库分离

module.exports = {
    optimization: {
        splitChunks: {
            cacheGroups: {
                commons: {
                    test: /(react|react-dom)/,
                    name: 'vendors',
                    chunks: 'all'
                }
            }
        }
    }
}

分离页面公共文件

module.exports = {
    optimization: {
        splitChunks: {
            minSize: 0,
            cacheGroups: {
                commons: {
                    name: 'commons',
                    chunks: 'all',
                    minChunks: 2 //最小引用次数
                }
            }
        }
    }
}

通过cdn引入

使用html-webpack-externals-plugin

new HtmlWebpackExternalsPlugin({
    externals: [
        {
            module: 'react',
            entry: 'https://unpkg.com/react@16/umd/react.production.min.js',
            global: 'React'
        },
        {
            module: 'react-dom',
            entry: 'https://unpkg.com/react-dom@16/umd/react-dom.production.min.js',
            global: 'ReactDOM'
        }
    ]

})

tree shaking 摇树

只把用到的方法打入bundle,没用到的方法就会在uglify阶段被擦除掉
注:必须是ES6的语法,CJS的方式不支持
production模式自动开启

Scope Hoisting

将所有模块的代码按照引入顺序放在一个函数作用域里,然后适当重命名一些变量防止变量名冲突
模块的引用次数大于1次是不生效
production模式自动开启ModuleConcatenationPlugin()


Dopp
1.1k 声望94 粉丝