wumi_blog icon indicating copy to clipboard operation
wumi_blog copied to clipboard

webpack 相关

Open 5Mi opened this issue 8 years ago • 3 comments

对webpack认识不透彻,反反复复搞来搞去好多遍每次都有新体验,一是对webpack理解不深,二是过一段时间根本就忘光了,再看也只是有印象(就像让我现在再看ionic angular一样),所以打算有时间把用webpack的经验总结一下,每次都有豁然开朗,灵光一闪的地方,再回头看却那么陌生,一定是我当时注释写的不好,再就是没有整体做总结的锅。。。

开坑待填

一个参考 又一个参考

5Mi avatar May 17 '16 06:05 5Mi

贴份标满注释的webpack.config.js

//-------------------------------------------------------------------------
//  export webpack config
//-------------------------------------------------------------------------

const process = require("process");
const path = require('path');
const webpack = require('webpack');
////提取出的样式没有html插件的话需手动在index页面内添加,此外这个插件好像还不支热重载
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const autoprefixer = require('autoprefixer');
const cssnext = require('postcss-cssnext');
const opacity = require('postcss-opacity');
const pixrem = require('pixrem');
const will_change = require('postcss-will-change');
const AssetsPlugin = require('assets-webpack-plugin');

//global.PUBLIC_PATH = '/static/'  develop.js
const PUBLIC_PATH = global.PUBLIC_PATH;
const DEBUG = process.env.NODE_ENV !== 'production';
//const VERBOSE = DEBUG;
const VERBOSE = false;
const WATCH = DEBUG;

const AUTOPREFIXER = {
    browsers: [
        'last 3 versions',
        'ie >= 9',
        'ie_mob >= 8',
        'ff >= 30',
        'chrome >= 31'
    ]
};


//-------------------------------------------------------------------------
//  Configuration for the client-side bundle (emc.js)
//-------------------------------------------------------------------------
const node_modules = path.join(process.cwd(), '/node_modules');

module.exports = {
    entry: {},
    output: {
        path: path.join(process.cwd(), '/app/static/'),
        /*
         * use out.publicPath='/webroot/public/assets', so that in your html, you can reference your js with <script src="/webroot/public/assets/bundle.js"></script>.
         * when you request webroot/public/assets/bundle.js the webpack-dev-server will find the js under the dist folder
         */
        // This option tells it where on your webpack-dev-server (server?) to load that bundle from. 当使用webpack-dev-server时能找到静态资源,换成实际服务器时无需修改引用的资源路径了
        //静态资源的引用路径 [https://github.com/webpack/docs/wiki/configuration#outputpublicpath]
        //publicPath: PUBLIC_PATH || 'static/',
        sourcePrefix: '',
        //chunkname我的理解是未被列在entry中,却又需要被打包出来的文件命名配置。
        //什么场景需要呢?在按需加载(异步)模块的时候,这样的文件是没有被列在entry中的,如使用CommonJS的方式异步加载模块
        //require.ensure(["modules/tips.jsx"], function(require) {
        //     var a = require("modules/tips.jsx");
        //        ...
        // }, 'tips');
        //异步加载的模块是要以文件形式加载哦,所以这时生成的文件名是以chunkname配置的,生成出的文件名就是tips.min.js。
        chunkFilename: DEBUG ? `js/[name].js` : `js/[name].[chunkhash:8].js`,
        filename: DEBUG ? `js/[name].js` : `js/[name].[chunkhash:8].js`
    },
    //使用的代码是合并以后的代码,不利于排错和定位,只需要在config中添加devtool 这样出错以后就会采用source-map的形式直接显示你出错代码的位置
    devtool: DEBUG ? 'cheap-module-eval-source-map' : false,

    resolve: {
        // 设置搜索目录
        root: [path.join(process.cwd(), '/src/js'), node_modules],
        //Replace modules with other modules or paths.
        //alias: {
        //  'vue': path.join(node_modules,'vue/dist/vue.js')
        //}
        alias: { },
        extensions: ['', '.js', '.scss', '.css']
    },
    module: {
        loaders: [
            // important: exclude files in node_modules 不包括node_modules中的js
            // otherwise it's going to be really slow!
            {test: /\.js$/, exclude:/node_modules\//, loader: 'babel'},
                                                                    //global.BUILD_TYPE = process.argv[3] || ''; // 接收pc,pad或是mobile
            {test: /\.(jpe?g|png|gif|svg)$/i, loader: 'url-loader?limit=10000&name=images/'+BUILD_TYPE+'/[name]'+(DEBUG?'.[hash:8]':'')+'.[ext]'},
            {test: /\.(woff2?|eot|ttf)$/i, loader: 'url?limit=10000&name=fonts/[name]'+(DEBUG?'.[hash:8]':'')+'.[ext]'},
            {test: /\.css$/, loader: ExtractTextPlugin.extract('style', 'css?'+(DEBUG?'sourceMap':'')+'!postcss')},
            {test: /\.scss$/, loader: ExtractTextPlugin.extract('style', 'css?'+(DEBUG?'sourceMap':'')+`!postcss!sass?`+(DEBUG?'sourceMap':'')+'')},
            {test: /\.vue$/, loader: 'vue'}
        ],
        //(不解析依赖)
        noParse: []
    },
    postcss: () => {
        return [
            will_change,
            cssnext(AUTOPREFIXER),
            opacity,
            pixrem
        ]
    },
    plugins: [
        new ExtractTextPlugin(DEBUG ? 'css/[name].css' : 'css/[name].[chunkhash:8].css', {
            disable: false,
            allChunks: false
        }),

        new webpack.optimize.OccurenceOrderPlugin(),

        //Define free variables.
        new webpack.DefinePlugin({
            //process.env指向当前shell的环境变量
            'process.env': {
                NODE_ENV: DEBUG ? '"develop"' : '"production"'
            },
            __DEV__: DEBUG,
            __PRO__: !DEBUG
        }),

        new webpack.optimize.CommonsChunkPlugin({
            name: 'vendors',
            filename: DEBUG ? 'js/[name].js' : 'js/[name].[hash:8].js',
            minChunks: function(module, count){
                // 被引用次数超过3次也认为是公共文件
                if (count >=2) return true;

                var resourceName = module.resource;
                if(resourceName){
                    resourceName = resourceName.substring(resourceName.lastIndexOf(path.sep)+1)
                }

                // 只要文件名是 *.common.*  或者 *.min.* 都认为是公共文件
                var reg_common = /\.common\.js($|\?)/i;
                var reg_min = /\.min\.js($|\?)/i;
                return reg_common.test(resourceName) || reg_min.test(resourceName);
            }
        }),

        //new webpack.ProvidePlugin({ }),

        ...(WATCH ? [
            new webpack.HotModuleReplacementPlugin(),
            new webpack.NoErrorsPlugin()
        ] : []),

        // all bundle records written in this file
        new AssetsPlugin({ filename: 'app/static/assets-map.json' }),

        // 压缩混淆
        ...(!DEBUG ? [
            new webpack.optimize.UglifyJsPlugin({
                exclude: /\.min\.js($|\?)/i,
                compress: {warnings: VERBOSE}
            })
        ] : [])
    ],
    //Cache generated modules and chunks to improve performance for multiple incremental builds.
    //This is enabled by default in watch mode.
    cache: DEBUG,
    //Switch loaders to debug mode.
    debug: DEBUG,
    //node api stats对象
    stats: {
        colors: true,
        reasons: DEBUG,
        hash: VERBOSE,
        version: VERBOSE,
        timings: true,
        chunks: VERBOSE,
        chunkModules: VERBOSE,
        cached: VERBOSE,
        cachedAssets: VERBOSE
    }

};

5Mi avatar May 25 '16 15:05 5Mi

  • noParse

webpack会花很多的时间查找一个库的依赖,使用该参数可以在webpack 中忽略对已知文件的解析

例如,这里我们可以确定 vue 是没有依赖项的,配置如下

// 支持正则匹配文件名
 module :{
   noParse: {
     'vue': './node_modules/vue/vue.min.js'
   }
 }

这样我们在项目中可以使用

import vue from 'vue'
  • alias

为引入模块提供别名,这个可以减少webpack去查找引入模块位置的时间,同时也为我们开发中引入公用模块提供方便

resolve: {
    alias: {
        'ui': path.resolve(__dirname, 'app/compontens/ui'),
        'fonts': path.resolve(__dirname, 'app/assets/fonts')
    }
}

以上配置可以让我们在需要引用公用组件时不必考虑目录层级的问题

import modal from 'ui/modal.vue'

css如果要使用webpack中的alias,需要在alias名前加上~

@font-face {
    url( "~fonts/iconfont.woff") format('woff')
}
  • uglifyJs
// 去除console
new webpack.optimize.UglifyJsPlugin({
  compress: {
    warnings: false,
    pure_funcs: [ 'console.log', 'console.info' ]
  },
}),

Webpack ProvidePlugin vs externals?参考 来自项目架构小结

5Mi avatar Apr 26 '17 02:04 5Mi

manifest commons-chunk-plugin

html-webpack-plugin

另 用手机等其他设备访问 webpack-dev-server

在webpack.config.js文件的devServer里加上host:'0.0.0.0',然后通过本地服务器就可以访问了。 参考问题 (别忘了关防火墙啥的)

5Mi avatar Apr 26 '17 07:04 5Mi