webpack 的作用

  1. 把你的应用拆分成多个文件;
  2. 可以构建打包 css、预处理css、编译js和图片等;
  3. 它支持 AMD 和 CommonJS,以及其他的模块系统(Angular, ES6)。

起步

webpack.config.js 文件

module.exports = {
    entry: './main.js',
    output: {
        filename: 'bundle.js'
    }
}

调用 webpack

  • webpack 开发环境下编译
  • webpack -p 产品编译及压缩
  • webpack --watch 开发环境下持续的监听文件变动来进行编译(非常快)
  • webpack -d 引入 source maps

编译 js

module.exports = {
    entry: './main.js',
    output: {
        filename: 'bundle.js'
    }
    module: {
        loaders: [
            {
                test: /\.coffee$/,
                loader: 'coffee-loader'
            },
            {
                test: /\.js$/,
                loader: 'babel-loader',
                query:{
                    presets: ['es2015', 'react']
                }
            }
        ]
    }
}
// 如果希望在 require 文件时省略文件的扩展名,
// 只需要在 webpack.config.js 中添加 resolve.extensions 来配置

module.exports = {
    entry: './main.js',
    output: {
        filename: 'bundle.js'
    }
    module: {
        loaders: [
            {
                test: /\.coffee$/, 
                loader: 'coffee-loader'
            },
            {
                test: /\.js$/,
                loaders: 'babel-loader',
                query: {
                    presets: ['es2015', 'react']
                }
            }
        ]
    },
    resolve: {
        //  现在 require 文件的时候可以直接使用 require('file), 不用使用         require('file.js')
        extensions: ['', '.js', '.json', '.coffee']
    }
}

css 样式和图片的加载

module.exports = {
    entry: './main.js',
    output: {
        path: './build', // 图片和 js 文件会放在这
        publicPath: 'http://mycdn.com/',  // 这里用来生成图片的地址
        filename: 'bundle.js'
    },
    module: {
        loaders: [
            {
                test: /\.less$/,
                loader: 'style-loader!css-loader!less-loader' // 用 ! 去链式调用 loader
            },
            {
                test: /\.css$/,
                loader: 'style-loader!css-loader'
            },
            {
                test: /\.(png|jpg)$/,
                loader: 'url?limit=8192'   // 内联的 base64 的图片地址,图片要小于 8k,直接的 url 的地址则不解析
            }
        ]
    }, 
    resolve: {
        extensions:['', '.js', '.json', '.coffee']
    }

};

功能标识

项目中有些代码我们只为在开发环境(例如日志)或者是内部测试环境(还没有发布的新功能)中使用,那就需要引入下面这些魔法全局变量:

if(__DEV__) {
    console.warn('Extra logging');
}

if(__PRERELEASE__) {
    showSecrectFeature();
}
var definePlugin = new webpack.definePlugins({
    __DEV__: JSON.stringify(JSON.parse(process.env.BUILD_DEV || 'true')),
    __PRERELEASE__: JSON.stringify(JSON.parse(process.env.BUILD_PRERELEASE || 'true'))
});

module.exports = {
    entry: './main.js',
    output: {
        filename: 'bundle.js',
    }
    plugins: [definePlugin]
}

多个入口文件

如果你有两个页面:profile 和 feed。如果你希望用户访问 profile 页面时不加载 feed 页面的代码,那就需要生成多个 bundles 文件:为每个页面创建自己的 'main module'(入口文件)

module.exports = {
    entry: {
        Profile: './profile.js',
        Feed: './feed.js'
    },
    output: {
        path: 'build',
        filename: '[name].js' // name 基于上边 entry 定义的 key
    }
};

优化通用代码

Feed 和 Profile 页面存在大量通用代码(比如 React、公共的样式和组件等等)。webpack 可以抽离页面间公共的代码,生成一个公共的 bundle文件, 供两个页面缓存使用:

var webpack = require('webpack');

var commonsPlugin = new webpack.optimize.CommonsChunkPlugin('common.js'); // 引入插件

module.exports = {
    entry: {
        Profile: './profile.js',
        Feed: './feed.js'
    },
    output: {
        path: 'build',
        filename: '[name].js'  // name 为上面 entry 的 key 值
    },
    plugins: [commonsPlugin]
};

异步加载

虽然 CommonJS 是同步加载的,但是 webpack 也提供了异步加载的方式。这对于单页应用中使用的客户端路由非常有用。当真正路由到了某个页面的时候,它的代码才会被加载下来。

if(window.location.pathname === './feed') {
    showLoadingState();
    require.ensure([], function(){
        hideLoadingState();
        require('./feed').show(); // 当这个函数调用的时候,此模块一定已经被同步加载下来了
    });
} else if (window.location.pathname === './profile') {
    showLoadingState();
    require.ensure([], function() {
        hideLoadingState();
        require('./profile').show();
    });
}

// webpack.config.js
output: {
    path: "/home/proj/public/assets", // webpack 的 build 路径
    publicPath: "/assets/"  // require 的路径
}