pengkobe / reading-notes

:stars: to record daily reading notes. I build an issue blog to record daily FE study notes. suggestion and comments are welcomed.
https://github.com/pengkobe/reading-notes/issues
MIT License
13 stars 1 forks source link

webpack #11

Open pengkobe opened 7 years ago

pengkobe commented 7 years ago

上一节分享了 gulp 结合实战的一些用法,这节 webpack 走起

它不是一个构建工具,而是 module bundler,webpack 就是根据 module 文件间的依赖将所有 module 打包(bundle)起来。其使用 loader 概念让配置更加容易,再也不用和一堆文件路径打交道了。

参考

pengkobe commented 7 years ago

配置

webpack的配置可以说就是module和plugins的配置,module里主要就是配置各种loaders, 没啥可说的,你要require什么类型的文件就去搜相应的loader就好, 这一节主要说后面的这个:plugins的配置。webpack支持非常多的插件,详见官方插件列表。

暴露jQuery

样,当webpack碰到require的第三方库中出现全局的$、jQeury和window.jQuery时,就会使用node_module下jquery包export出来的东西了。

new webpack.ProvidePlugin({
    $: "jquery",
    jQuery: "jquery",
    "window.jQuery": "jquery"
})

定义全局标识

在命令行传参可以指定是时开发还是发布,

// 依赖yargs
args = require('yargs').argv;
new webpack.DefinePlugin({
    __PROD__: args.prod,
    __MOCK__: args.mock
}),

这样在build时传入--prod,则变量PROD即为true,传入--mock则MOCK为true。 在JS代码中就可以使用类似的判断if (PROD) {...}了。

输出单独的JS

可以使用webpack内置的CommonsChunkPlugin,

entry: {
    app: [
        'source/app/index.js'
    ],
    vendor: [
        'angular',
        'angular-ui-router',
        'angular-animate'
        // ...
    ]
}
new webpack.optimize.CommonsChunkPlugin('vendor', isProd ? 'vendor.[hash].js' : 'vendor.js')

这样,所有模块中只要有require到vendor数组中定义的这些第三方模块, 那么这些第三方模块都会被统一提取出来,放入vendor.js中去。 在插件的配置中我们还进行了判断,如果是生产环境则给最终生成的文件名加hash。

一些有用的工具

Demo

个人有使用webpack结合vue开发了一个项目:my-twitter-system ,欢迎start。

pengkobe commented 7 years ago

马斯特的配置

个人觉得这个配置实在太美

var webpack = require('webpack');
var ExtractTextPlugin = require("extract-text-webpack-plugin");
var HtmlWebpackPlugin = require('html-webpack-plugin');
var CopyWebpackPlugin = require('copy-webpack-plugin');
var autoprefixer = require('autoprefixer');
var args = require('yargs').argv;

// parameters
var isProd = args.prod;
var isMock = args.mock;

var base = './';
// use mock api or not
var entryJs = isMock ?
    base + 'source/test/e2e/mocks/index.js' :
    base + 'source/app/index.js';
var appName = isMock ? 'appTest' : 'app';

var plugins = [
    new webpack.ProvidePlugin({
        $: "jquery",
        jQuery: "jquery",
        // materialize-css rely on this to support velocity
        "window.jQuery": "jquery"
    }),
    new webpack.DefinePlugin({
        __PROD__: isProd,
        __MOCK__: isMock
    }),
    new webpack.optimize.CommonsChunkPlugin('vendor', isProd ? 'vendor.[hash].js' : 'vendor.js'),
    new ExtractTextPlugin(isProd ? '[name].[hash].css' : '[name].css'),
    new HtmlWebpackPlugin({
        template: 'jade!./source/app/index.jade',
        chunks: ['app', 'vendor'],
        favicon: 'favicon.ico',
        appName: appName
    }),
    new CopyWebpackPlugin([
        { from: 'node_modules/babel-core/browser-polyfill.min.js', to: 'polyfill.js'}
    ])
];

if (isProd) {
    plugins.push(
        new webpack.NoErrorsPlugin(),
        new webpack.optimize.DedupePlugin(),
        new webpack.optimize.UglifyJsPlugin({
            compress: {
                warnings: false
            },
            mangle: false
        }),
        new webpack.optimize.OccurenceOrderPlugin()
    );
}

module.exports = {
    entry: {
        app: [
            entryJs
        ],
        vendor: [
            // 3rd dependencies
            'materialize-css/bin/materialize.css',
            'materialize-css/bin/materialize.js',
            'animate.css/animate.css',
            // angular
            'angular',
            'angular-ui-router',
            'angular-animate',
            'angular-messages',
            'angular-mocks',
            'angular-loading-bar',
            'oclazyload'
        ]
    },
    output: {
        path: base + 'build',
        filename: isProd ? '[name].[hash].js' : '[name].js',
        chunkFilename: isProd ? '[name].[hash].chunk.js' : '[name].chunk.js'
    },
    module: {
        preLoaders: [
            {
                test: /\.js$/,
                loader: "eslint",
                exclude: /node_modules/
            }
        ],
        loaders: [
            {
                test: /\.js$/,
                loader: 'babel',
                exclude: /node_modules/
            },
            {
                test: /\.html$/,
                loader: 'html'
            },
            {
                test: /\.jade$/,
                loader: 'jade',
                exclude: /index\.jade/
            },
            {
                test: /\.styl$/,
                loader: ExtractTextPlugin.extract('vue-style', 'css?sourceMap!postcss!stylus')
            },
            {
                test: /\.css$/,
                loader: ExtractTextPlugin.extract('vue-style', 'css?sourceMap')
            },
            {
                test: /\.(woff|woff2|ttf|eot|svg)(\?]?.*)?$/,
                loader : 'file?name=assets/fonts/[name].[ext]?[hash]'
            },
            {
                test: /\.(png|jpg)$/,
                loader: 'url?limit=8192&name=assets/images/[name].[hash].[ext]'
            }
        ]
    },
    plugins: plugins,
    debug: !isProd,
    devtool: isProd ? 'source-map' : 'eval-source-map',
    devServer: {
        contentBase: base + 'build',
        historyApiFallback: true,
        stats: {
            modules: false,
            cached: false,
            colors: true,
            chunk: false
        },
        host: '0.0.0.0',
        port: 8080
    },
    postcss: function () {
        return [autoprefixer];
    }
};
pengkobe commented 7 years ago

gulp 与 webpack 的区别于联系

建议参照该帖:
https://www.zhihu.com/question/45536395/answer/164361274