一个合格的Webpack4配置工程师素养:第一部分

发布于 2019-01-29 作者 coder 383次 浏览 版块 分享

原文: https://cnodejs.org/topic/5c4d498a595cbd1e95088cd0

标题党

总结Webpack4常见的配置, 含DEMO, 一步步肥肠详细,略长, 后续结束时候我们给出源码文件。

准备开发环境

- 安装node
- 安装webpack
- npm init 初始化项目

目录结构

写跑一个小demo

// src/index.js

import _ from 'lodash'

function create_div_element () {
    const div_element = document.createElement('div')
    div_element.innerHTML = _.join(['kobe', 'cpul'], ' ')
    return div_element
}

const div_ele = create_div_element()
document.body.appendChild(div_ele)
// dist/index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>webpack4</title>
</head>
<body>
    <script src="./bound.js"></script>
</body>
</html>

// webpack.config.js

const path = require('path')

module.exports = {
    entry: './src/index.js',
    mode: 'development',
    output: {
        filename: 'bound.js',
        path: path.resolve(__dirname, 'dist')
    }
}

然后通过npx执行webpack进行打包。

或者配成一个script命令也可以。

"scripts": {
    "build": "npx webpack -c webpack.config.js"
 }
 npx webpack

在浏览器打开index.html就会发现代码执行成功了。

webpack处理CSS

假设我们现在需要在index.js引入css文件。

 // index.js

import './style/reset.css'

我们需要使用专门的loader来解析css, 并把css注入到html文件

npm i -D css-loader style-loader

修改webpack配置文件

const path = require('path')

module.exports = {
    entry: './src/index.js',
    mode: 'development',
    output: {
        filename: 'bound.js',
        path: path.resolve(__dirname, 'dist')
    },
    module: {
        rules: [
            {
                test: /\.css/,
                use: ['style-loader', 'css-loader'] // use的顺序从右往左
            }
        ]
    }
}

这个时候你在npx webpack, 打包后执行index.html你会发现css已经注入成功了。

webpack处理sass文件

现在前端项目都是使用一些css预处理器来帮助更好的使用CSS,如Sass等。

假设我们现在index.js中需要引入一个base.scss文件。 那么webpack改如何处理sass/scss文件呢?

npm install sass-loader node-sass -D
// src/style/base.scss

$bd-bg: pink;
body {
    background: $bd-bg;
}
// index.js

import './style/base.scss'

更过配置文件处理scss

const path = require('path')

module.exports = {
    entry: './src/index.js',
    mode: 'development',
    output: {
        filename: 'bound.js',
        path: path.resolve(__dirname, 'dist')
    },
    module: {
        rules: [
            {
                test: /\.(sc|sa|c)ss$/,
                use: ['style-loader', 'css-loader', 'sass-loader'] // use的顺序从右往左
            }
        ]
    }
}

webpack为sass添加source map

配置source map是为了当出现错误时候方便我们进行定位调试, 当然我们在生产环境不需要启动这个。
像我们上面例子中, 你会发现打包后我们看不出scss来自哪个文件。

修改webpack配置文件。

const path = require('path')

module.exports = {
    entry: './src/index.js',
    mode: 'development',
    output: {
        filename: 'bound.js',
        path: path.resolve(__dirname, 'dist')
    },
    module: {
        rules: [
            {
                test: /\.(sc|sa|c)ss$/,
                use: [
                    {
                        loader: 'style-loader'
                    },
                    {
                        loader: 'css-loader',
                        options: {
                            sourceMap: true
                        }
                    },
                    {
                        loader: 'sass-loader',
                        options: {
                            sourceMap: true
                        }
                    }
                ]
            }
        ]
    }
}

打包后在浏览器打开index.html.

webpack为css添加CSS3前缀

PostCSS是一个用 JavaScript 工具和插件转换 CSS 代码的工具, 功能强大, 我们最常用的就是利用PostCSS帮我们Autoprefixer 自动获取浏览器的流行度和能够支持的属性,并根据这些数据帮你自动为 CSS 规则添加前缀。

npm i -D postcss-loader autoprefixer postcss-import

// postcss-import: 在使用@import css文件时候让webpack可以监听并编译
// postcss-nextcss: 支持css4

修改配置文件

rules: [
    {
        test: /\.(sc|sa|c)ss$/,
        use: [
            {
                loader: 'style-loader'
            },
            {
                loader: 'css-loader',
                options: {
                    sourceMap: true
                }
            },
            {
                loader: 'postcss-loader',
                options: {
                    ident: 'postcss',
                    sourceMap: true,
                    plugins: loader => [
                        // 可以配置多个插件
                        require('autoprefixer')({
                            browsers: [' > 0.15% in CN ']
                        })
                    ]
                }
            },
            {
                loader: 'sass-loader',
                options: {
                    sourceMap: true
                }
            }
        ]
    }
]

抽离样式表为单独的css文件并打版本号

抽离css前提是我们只在生产环境这么做, 因此你的配置文件的mode: production。

另外抽离了css就不能在使用style-loader注入到html文件。

npm i -D mini-css-extract-plugin

配置一个script命名

"scripts": {
    "dist": "cross-env NODE_ENV=production npx webpack --progress --config webpack.prod.config.js"
},

添加一个webpack.prod.config.js.当然正式项目我们是会拆分配置文件, 然后通过merge处理。

- webpack.base.config.js
- webpack.dev.config.js
- webpack.prod.config.js
- webpack.vue.config.js

这里demo就没有这么做, 所以代码有些冗余。

// webpack.prod.config.js

const path = require('path')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const devMode = process.env.NODE_ENV !== 'production'

module.exports = {
    entry: './src/index.js',
    mode: 'production',
    output: {
        filename: 'bound.js',
        path: path.resolve(__dirname, 'dist')
    },
    module: {
        rules: [
            {
                test: /\.(sc|sa|c)ss$/,
                use: [
                    MiniCssExtractPlugin.loader,
                    {
                        loader: 'css-loader'
                    },
                    {
                        loader: 'postcss-loader',
                        options: {
                            ident: 'postcss',
                            plugins: (loader) => [
                                require('autoprefixer')({
                                    browsers: [
                                        'last 10 Chrome versions',
                                        'last 5 Firefox versions',
                                        'Safari >= 6',
                                        'ie > 8'
                                    ]
                                })
                            ]
                        }
                    },
                    {
                        loader: 'sass-loader'
                    }
                ]
            }
        ]
    },
    plugins: [
        new MiniCssExtractPlugin({
            filename: devMode ? '[name].css' : '[name].[hash:5].css', // 设置输出的文件名
            chunkFilename: devMode ? '[id].css': '[id].[hash:5].css'
        })
    ]
}

打包后你会发现

这个时候我们如果去使用只能在index.html去引用它了, 很明显这是不方便的, 因为我们css文件肯定很庞大, 后面会解决这个问题, 这里就略过。

webpack压缩JS和CSS

压缩的作用自然是为了减小包的体积了, 提升加载效率, 因此压缩都是配置在生产环境。

压缩css

Webpack后面版本应该会内置CSS压缩, 目前先手工配置。

npm i -D optimize-css-assets-webpack-plugin

更改配置文件:

const OptimizeCSSAssertsPlugin = require('optimize-css-assets-webpack-plugin')

optimization: {
    minimizer: [
        // 压缩CSS
        new OptimizeCSSAssertsPlugin({})
    ]
}

JS压缩

npm i -D uglifyjs-webpack-plugin

修改配置文件

const UglifyJsPlugin = require('uglifyjs-webpack-plugin')

optimization: {
    minimizer: [
        // 压缩JS
        new UglifyJsPlugin({
            // 有很多可以配置
            cache: true,
            parallel: true,
            sourceMap: true,
            uglifyOptions: {
                 // 在UglifyJs删除没有用到的代码时不输出警告
                warnings: false,
                output: {
                    // 删除所有的注释
                    comments: false,
                    // 最紧凑的输出
                    beautify: false
                },
                compress: {
                    // 删除所有的 `console` 语句
                    // 还可以兼容ie浏览器
                    drop_console: true,
                    // 内嵌定义了但是只用到一次的变量
                    collapse_vars: true,
                    // 提取出出现多次但是没有定义成变量去引用的静态值
                    reduce_vars: true,
                }
            }
        })
    ]
}

这个时候去打包我发现一个错误, ERROR in js/background.js from UglifyJs Unexpected token: keyword (const)。

Uglify-js不支持es6语法,请使用terser插件, 于是我们更改使用terser插件试试, 其实你继续用uglifyjs-webpack-plugin也可以, 只需要配合babel先转下。

npm install terser-webpack-plugin -D

更多使用见官网terser-webpack-plugin

optimization: {
    minimizer: [
        // 压缩JS
        new TerserPlugin({
            cache: true,
            parallel: true,
            sourceMap: true,
            // 等等详细配置见官网
        }),

    ]
}

收藏
暂无回复