1

前言

最近项目中在使用react/redux/koa做一个IM,打包工具自然选择了webpack

我主要使用了webpack 的下列功能

  1. webpack 打包编译js文件

  2. 编译js文件支持多入口,版本控制,懒加载

  3. js和样式文件都支持热替换,不需要每个简单的修改都要刷新等待

  4. 复杂的css sprites功能,支持sass 语法

  5. 支持sourcemap,无论在开发还是上线的时候都支持soucemap的功能

webpack的功能不止这些了,而且社区比较活跃,插件开发也挺容易的,真心不错的一个工具

下面是具体功能实现部分

---------- 我是华丽的分割线 ----------

js 编译相关

webpack最基础的功能就是编译js了,由于react最近比较火热,而且react项目大部分都是通过webpack 进行打包编译的,导致很多人认为webpack 只是适用于react项目,这是不对的,webpack适用于所有的前端项目
我的项目也在使用react和sass

    entry: [
        vendorCss: [
            config.src.js + '/css/jquery.Jcrop.css'
        ],
        app: [
            config.src.js + '/main.jsx'],
        vendors:vendors]
     },
    output: {
        path: config.dest.js,
        filename: '[name].[chunkhash].js'
    },
    module: {
        loaders:[{
                test: /\.jsx?$/,
                exclude: /node_modules/,
                loaders: ['babel-loader'] //babel必须放在第一位,不然sourcemap是编译后的代码
            }, {
                test: /\.(png|jpg|gif)$/, loader: 'file-loader'
            },{
                test: /\.scss/,
                loader: 'style!css!postcss!sass?sourceMap'
            }, {
                test: /\.css/,
                loader: 'style!css'
            }
        ],
        noParse: [
            path.join(__dirname + '/client/node_modules/jquery/'),
            path.join(__dirname + '/client/lib/**')
        ]
    }
    

上面是一个简单的配置,页面的脚本分为两个vendor.js和app.js

上面的代码有一些潜在的坑:

  1. output.filename 中[name].[chunkhash] 中的chunkhash 并不只是内容变得时候才更新,默认的跟机器名,时间戳都有关系,如果要只是生成文件内容的md5,可以使用
    [webpack-md5-hash] ,也就是在plugins 里面添加 new WebpackMd5Hash()

  2. jsx的babel-loader必须放在第一位,如果需要jsx-loader,那么顺序就是
    ['babel-loader', 'jsx-loader'],否则生成的soucemap 代码是babel 编译后的es5 代码

  3. 关于懒加载,除了多入口的方式,也可以在项目中使用require.ensure的方式,点击此处查看更多

  4. 支持soucemap的话可以配置devtool 为'#cheap-module-eval-source-map',devtool有很多种,常见的sourcemap有下面几个问题

    1) sourcemap的代码是babel编译后的,这个主要是因为配置了devtool为eval,cheap-source-map
    2) sourcemap 中文乱码了,这个主要是配置了含有eval的devtool, 比如cheap-module-eval-source-map
    
    因此推荐开发的时候使用的sourcemap:cheap-module-source-map
    
    

    更多可以点此此处

上线后代码会经过uglifyJsPlugin进行压缩,下面是相关配置

     new webpack.optimize.UglifyJsPlugin({
        compress: {
            warnings: false
        },
        sourceMap: true,//这里的soucemap 不能少,可以在线上生成soucemap文件,便于调试
        mangle: true
    })
  1. 上线后的devtool要配置为source-map,有时候为了性能考虑,一定要配置这个插件

    new webpack.DefinePlugin({

       'process.env': {
           NODE_ENV: '"production"'
       }

    })

  2. 可以在项目中配置一些alias,具体的可以查看此处,alias可以解决一些模块嵌套层级比较深,相对路径不好引用的bug

  3. 项目编译后生成的js 如果放到html页面里面呢?这里我自己写了一个插件,
    使用gulp-template 进行文件替换。

    export function  buildViewHtml(dev) {
        return function () {
            this.plugin("done", function (stats) {
                stats = stats.toJson();
                
                let result = dev ? processDevHtml() : processProdHtml(stats.assetsByChunkName);//注意assetsByChunkName字段,包含chunkhash这些值
                let sourceViewFile = path.join(__dirname, 'client', 'index.html');
                let viewFile = path.join(__dirname, 'views');
                gulp.src(sourceViewFile)
                    .pipe(template({
                        CSSHASH: result.cssHash ? JSON.stringify(result.cssHash) : null,
                        appJS: result.app,
                        vendorCss: result.vendorCss || null,
                        vendorsJS: result.vendors
                    }))
                    .pipe(gulp.dest(viewFile));
    
            });
        }
    }

使用的时候在plugins里面配置上buildHtml(false)

下面的内容是hrm相关的,今天先写到这里,后续会补充更多


热替换 Hot Module Replacement

热替换(Hot Module Replacement),简称HMR
是说应用可以动态的更新局部模块代码,而不需要刷新整个页面

这个在跨平台开发或者较复杂的项目中特别有用,比如我有个层级很深的操作,操作了10多次才进入这个界面,这个时候更改了一个小功能,如果没有热替换,只能刷新整个页面,再重复操作10多次才能看到效果,热替换改变了这一切


qinghui
164 声望8 粉丝

码农一枚,目前在美团做前端工作


« 上一篇
koa-源码分析