webpack1升级webpack2

作者: vvkee | 来源:发表于2017-03-12 11:47 被阅读1650次

    webpack2终于正式发布了。最近几天一直在调研webpack2的升级成本,因为公司的移动端使用的是webpack1,升级的目的也是为了之后pc端做一些铺路吧。

    项目目录

    Paste_Image.png

    bulid目录

    glup中的task配置,webpack环境配置,不同环境不同编译。支持热替换。

    node_modules

    这个不用说了吧。

    src

    主目录,也是需要编译的目录。里面的modules是react的代码,resources是静态文件,比如字体文件、图片、全局scss等

    开始升级

    看了一遍升级文档,然后一项项配置。每配置完一项之后都试着在本地环境去运行,看看有哪些错误,然后一个个解决。自动化工程我觉得就是在试错中才会成功。

    resolveLoader

    在webpack1中,resolveLoader配置root属性已经被modules所替换
    webpack1版本:

    resolveLoader: {
        root: path.join(rootPath, 'node_modules')
    }
    

    webpack2版本:

    resolveLoader: {
        modules: ['node_modules']
    }
    

    module

    module里面最主要的变化还是挺大的,这应该也是这次webpack团队的升级核心。

    1. 变化一,loaders属性被rules替换。
    2. 变换二,preLoaders被剔除,将在rules里面进行配置
    3. 变化三,loader不再支持缩写,如果想要支持缩写还得配置,这里不进行配置缩写项,因为我觉得没必要。
    4. 变化四,添加options属性。

    webpack1代码如下

    module: {
        // preLoaders属性将被剔除
        preLoaders: [{
            test: /modules\/\S*\.jsx?$/,
            loader: 'eslint',                      // loader将不支持简写而需要写成eslint-loader
            include: rootPath,
            exclude: /node_modules/
        }],
        // loaders属性将被rules替换
        loaders: [{
            test: /\.ejs$/,
            loader: 'ejs-loader'
        }, {
            test: /\.(jpe?g|png|gif)$/i,
            loader: 'url?limit=10000&name=images/[name].[hash:7].[ext]',
        }, {
            test: /\.(svg|woff2?|eot|ttf|otf)(\?.*)\S*$/,
            loader: 'url',
            query: {
                limit: 10000,
                name: 'fonts/[name].[hash:7].[ext]'
            }
        }]
    }
    

    webpack2代码如下

    module: {
            rules:[
                {
                    test: /modules\/\S*\.jsx?$/,
                    loader: 'eslint-loader',
                    include: rootPath,
                    // enforce这个属性要注意一下,之前的preLoader被剔除了,但webpack2还是提供了代替方案。
                    enforce: "pre",
                    exclude: /node_modules/,
                    options: {
                        formatter: require('eslint-friendly-formatter')
                    }
                },
                {
                    test: /\.ejs$/,
                    loader: 'ejs-loader'
                },
                {
                    test: /\.(jpe?g|png|gif)$/i,
                    loaders: [{
                        loader: 'file-loader',
                        options: {
                            name: 'images/[name].[hash:7].[ext]'
                        }
                    }, {
                        loader: 'image-webpack-loader',
                        options: {
                            mozjpeg: {
                                progressive: true,
                            },
                            gifsicle: {
                                interlaced: false,
                            },
                            optipng: {
                                optimizationLevel: 7,
                            },
                            pngquant: {
                                quality: '65-90',
                                speed: 4
                            }
                        }
                    }],
    
                }, {
                    test: /\.(ttf|eot|svg|woff(2)?)(\?[a-z0-9=&.]+)?$/,
                    loader: 'file-loader',
                    options: {
                        name: 'fonts/[name].[hash:7].[ext]'
                    }
                }
            ]
        },
    

    可以看到webpack2新增enforce属性来代替preLoader。

    loader options

    webpack2配置项中eslint、postcss的这些原本属于loader里的属性会被移除,并且编译会报错!
    比如我在webpack1中的配置是这样的

    import webpack from 'webpack'
    import autoprefixer from 'autoprefixer'
    import precss from 'precss'
    import postcssScss from 'postcss-scss'
    import path from 'path'
    import postcssImport from 'postcss-import'
    const rootPath = path.join(__dirname, '..')
    
    export default  {
        entry: {
            'app': [`${rootPath}/src/modules/main.jsx`],
        },
        resolve: {
            root: [`${rootPath}/src`, `${rootPath}/node_modules`],
            extensions: ['', '.js', '.jsx', '.css', '.scss', '.json']
        },
        resolveLoader: {
            root: path.join(rootPath, 'node_modules')
        },
        module: {
            preLoaders: [
                {
                    test: /modules\/\S*\.jsx?$/,
                    loader: 'eslint',
                    include: rootPath,
                    exclude: /node_modules/
                }
            ],
            loaders: [
                {
                    test: /\.ejs$/,
                    loader: 'ejs-loader'
                },
                {
                    test: /\.(jpe?g|png|gif)$/i,
                    loader: 'url?limit=10000&name=images/[name].[hash:7].[ext]',
                }, {
                    test: /\.(svg|woff2?|eot|ttf|otf)(\?.*)\S*$/,
                    loader: 'url',
                    query: {
                        limit: 10000,
                        name: 'fonts/[name].[hash:7].[ext]'
                    }
                }
            ]
        },
        // webpack2报错!!!
        eslint: {
            formatter: require('eslint-friendly-formatter')
        },
       // webpack2报错!!!
        postcss: function (webpack) {
            return {
                plugins: [
                    postcssImport({
                        glob: true,
                        onImport: function (files) {
                            files.forEach(this.addDependency)
                        }.bind(this),
                        path: `${rootPath}/src`
                    }),
                    precss({
                        import: {
                            disable: true
                        }
                    }),
                    autoprefixer({ browsers: [ 'last 2 versions' ] }),
    
                ],
                parser: postcssScss
            }
        }
    }
    

    但webpack2中还是提供了响应的方法,就是将这些配置写到rule里的options之中。比如eslint-loader

    rules:[{
        test: /modules\/\S*\.jsx?$/,
        loader: 'eslint-loader',
        include: rootPath,
        enforce: "pre",
        exclude: /node_modules/,
        // webpack1中的配置项需要写到这
        options: {
            formatter: require('eslint-friendly-formatter')
         }
    }]
    

    至于postcss之后我会说下遇到的坑。

    postcss

    前面已经说到loader options不能配置到config中,然后这个postcss还是挺特别的。因为我写到postcss-loader里面是不管用的。然后根据webpack2提供的插件LoaderOptionsPlugin我把postcss写进去,在local环境的时候,不使用extract-text-webpack-plugin分离css的情况下是编译成功的。代码如下:

    var autoprefixer = require('autoprefixer');
    var precss = require('precss');
    var postcssScss = require('postcss-scss');
    var postcssImport = require('postcss-import');
    var sprites = require('postcss-sprites');
    var sassyMixins = require('postcss-sassy-mixins');
    export default  {
       ....
        plugins: [
          new webpack.LoaderOptionsPlugin({
              postcss: {
                  plugins: [
                      postcssImport({
                      glob: true,
                      path: './src'
                   }),
                  sassyMixins(),
                  precss(),
                  autoprefixer({ browsers: [ 'last 2 versions' ] }),
              ],
              parser: postcssScss
             }
          })
           ...
        ]
    }
    

    extract-text-webpack-plugin

    在这个插件中,webpack2也是改动较大的地方,它的参数变成了一个对象。
    在webpack1中

    const extractCSS = new ExtractTextPlugin('css/[name].min.[contenthash:8].css', {
        allChunks: false
    })
    

    webpack2

    // new ExtractTextPlugin(options: filename | object)
    
    new ExtractTextPlugin({
        id: '{string}',
        filename: '{string}' || function () {},
        allChunks: {bool},
        disable: {bool},
        ignoreOrder: {bool}
    })
    

    接着是loader的配置,在webpack1中,还是以参数的形式传递

    const cssLoader = extractCSS.extract(
        'style-loader',
        `css-loader?sourceMap&minimize&modules&localIdentName=[name]__[local]___[hash:base64:5]&importLoaders=1!postcss-loader?sourceMap`
    )
    const globalCssLoader = extractCSS.extract(
        'style-loader',
        `css-loader?sourceMap&minimize&importLoaders=1!postcss-loader`
    )
    

    在webpack2中更变为object

    const cssLoader = extractCSS.extract({
        fallback: 'style-loader',
        use: [{
            loader: 'css-loader',
            options: {
                sourceMap: true,
                minimize: true,
                modules: true,
                importLoaders: 1,
                localIdentName: '[name]__[local]___[hash:base64:5]'
            }
        }, {
            loader: 'postcss-loader'
        }]
    })
    const globalCssLoader = extractCSS.extract({
        fallback: 'style-loader',
        use: [{
            loader: 'css-loader',
            options: {
                sourceMap: true,
                importLoaders: 1,
                minimize: true
            }
        }, {
            loader: 'postcss-loader'
        }]
    })
    

    是不是很简单。但在这我又遭遇到了一个坑!那就是postcss问题,我在编译的时候postcss爆出一个错误,说是读不到配置文件。在google找一圈,他们给出的解决方案是用webpack2中的LoaderOptionsPlugin来解决,但我没解决成功,肯定是有哪些步骤出错了。
    然后我在google的时候发现有人提到在根目录下创建一个postcss.config.js文件。根据postcss文档的提示,我推断了一下,postcss在运行的时候,先是会匹配它的options,但若没有匹配上,那么它就会去根目录去找postcss.config.js文件!之后,我把base里面的postcss配置都提出来放到根目录下,这样代码也解耦了一部分。
    postcss.config.js

    var autoprefixer = require('autoprefixer');
    var precss = require('precss');
    var postcssScss = require('postcss-scss');
    var postcssImport = require('postcss-import');
    var sprites = require('postcss-sprites');
    var sassyMixins = require('postcss-sassy-mixins');
    module.exports = {
        plugins: [
            postcssImport({
                glob: true,
                path: './src'
            }),
            sassyMixins(),
            precss(),
            autoprefixer({ browsers: [ 'last 2 versions' ] }),
        ],
        parser: postcssScss
    };
    

    试着编译一下,成功!

    Paste_Image.png

    总结

    webpack1升级到webpack2其实挺简单的,并且成本很低。最后还是得编译的速度,打包的体积进行优化。在webapp中600K确实是非常大了,自家人用,加上gzip的话230K左右,用上cdn,大概在15KB这样。webpack2有个新特性,就是Tree Shaking,之后尝试下这个工具。对了,安利下yarn,安装包速度炒鸡快!并且和npm无痛切换,就是在linux安装麻烦了些!

    相关文章

      网友评论

      本文标题:webpack1升级webpack2

      本文链接:https://www.haomeiwen.com/subject/epjtnttx.html