zoukankan      html  css  js  c++  java
  • webpack学习

    学习地址:

    http://blog.csdn.net/zaichuanguanshui/article/details/53610694 //配置参数意义

    http://blog.csdn.net/zaichuanguanshui/article/details/53611379 //常用插件

    出处: https://segmentfault.com/a/1190000006201049

    前情提要

    上一篇文章介绍了目前前端比较流行的各种编辑器,以及各种流行的打包方式,最后给了一个Gulp的例子,这个例子还是14年的时候写的,还有一些可以优化的空间,就不讨论了,这篇文章主要讲目前火热的打包构建方式--Webpack的使用方式。

    主菜--没有开胃汤

    其实Webpack的入门指导文章非常多,配置方式也各有各样,这里我推荐题叶大神的入门级指南--Webpack 入门指迷,如果不知道Webpack是什么或者不是很清楚各项配置含义的开发者,可以看此文章扫扫盲。毕竟我这篇文章并不是特别基础。

    一、base.js

    var path = require('path')
    var baseConfig = {
        resolve: {
            extensions: ['', '.js'],
            fallback: [path.join(__dirname, '../node_modules')],
            alias: {
                'src': path.resolve(__dirname, '../src'),
                'assets': path.resolve(__dirname, '../src/assets'),
                'components': path.resolve(__dirname, '../src/components')
            }
        },
        module: {
            loaders: [{
                test: /.js$/,
                loader: 'babel',
                exclude: /node_modules/
            }, {
                test: /.(png|jpe?g|gif|svg|woff2?|eot|ttf|otf)(?.*)?$/,
                loader: 'url?limit=8192&context=client&name=[path][name].[hash:7].[ext]'
            },
            {
                test: /.css$/,
                loader: 'style!css!autoprefixer',
            },
            {
                test: /.scss$/,
                loader: 'style!css!autoprefixer!sass'
            }]
        }
    };
    
    module.exports = baseConfig;
    

      

    解读下这个基本配置:

    1、resolve 解析模块依赖的时候,受影响的配置项。

    • extensions 决定了哪些文件后缀在引用的时候可以省略点,Webpack帮助你补全名称。

    • fallback 当webpack在 root(默认当前文件夹,配置时要绝对路径) 和 modulesDirectories(默认当前文件夹,相对路径)配置下面找不到相关modules,去哪个文件夹下找modules

    • alias 这个大家应该比较熟悉,requirejs之类的都有,就是别名,帮助你快速指向文件路径,少写不少代码,而且不用关心层级关系, 需要注意的是:在scss之类的css预编译中引用要加上~,以便于让loader识别是别名引用路径。

    2、module 解析不同文件使用哪些loader,这个比较简单,很多文章都有,就不多说了,注意的是,这里的scss可以换成你自己的预编译器,例如:sass、less、stylus等,或者直接用postcss都行,当然还可以用一种通用方法,后面补上。

    二、开发环境配置--config

    var webpack = require('webpack');
    var path = require('path')
    var merge = require('webpack-merge')
    var baseConfig = require('./webpack.base')
    var getEntries = require('./getEntries')
    
    var hotMiddlewareScript = 'webpack-hot-middleware/client?reload=true';
    
    var assetsInsert = require('./assetsInsert')
    
    module.exports = merge(baseConfig, {
      entry: getEntries(hotMiddlewareScript),
      devtool: '#eval-source-map',
      output: {
        filename: './[name].[hash].js',
        path: path.resolve('./dist'),
        publicPath:'./dist'
      },
      plugins: [
        new webpack.DefinePlugin({
          'process.env': {
            NODE_ENV: '"development"'
          }
        }),
        new webpack.optimize.OccurenceOrderPlugin(),
        new webpack.HotModuleReplacementPlugin(),
        new webpack.NoErrorsPlugin(),
        new assetsInsert()
      ]
    })
    

      

    说说这个配置中的一些难点:

    1、getEntries 是用来配置入口文件,一般很多人是自己手写,或者SPA页面,只有一个入口, 很容易就写出来,但是公司中,很多情况,是需要多入口,也就是多路由的Url,这个时候入口的配置就比较麻烦,我这里是放单独一个文件里面配置,我们公司是靠规定来执行,也就是一个文件夹所有的main.js都认为是入口文件,其他都忽略。

    function getEntry(hotMiddlewareScript) {
        var pattern = paths.dev.js + 'project/**/main.js';
        var array = glob.sync(pattern);
        var newObj = {};
    
        array.map(function(el){
            var reg = new RegExp('project/(.*)/main.js','g');
            reg.test(el);
            if (hotMiddlewareScript) {
                newObj[RegExp.$1] = [el, hotMiddlewareScript];
            } else {
                newObj[RegExp.$1] = el;
            }
        });
        return newObj;
    }
    

      

    2、assetsInsert 是用来做模板替换的,一个小插件把template里面的值替换成打包后的css或者js。

    三、打包环境配置--production

    var webpack = require('webpack');
    var path = require('path')
    var merge = require('webpack-merge')
    var baseConfig = require('./webpack.base')
    var getEntries = require('./getEntries')
    var ExtractTextPlugin = require('extract-text-webpack-plugin');
    var assetsInsert = require('./assetsInsert')
    
    var productionConf = merge(baseConfig, {
        entry: getEntries(),
        output: {
            filename: './[name].[hash].js',
            path: path.resolve('./public/dist'),
            publicPath: './'
        },
        plugins: [
            new webpack.DefinePlugin({
                'process.env': {
                    NODE_ENV: '"production"'
                }
            }),
            new ExtractTextPlugin('./[name].[hash].css', {
                allChunks: true
            }),
            new webpack.optimize.UglifyJsPlugin({
                compress: {
                    warnings: false
                }
            }),
            new webpack.optimize.OccurenceOrderPlugin(),
            new assetsInsert()
        ]
    })
    
    productionConf.module.loaders = [
                 {
                    test: /.js$/,
                    loader: 'babel',
                    exclude: /node_modules/
                }, {
                    test: /.(png|jpe?g|gif|svg|woff2?|eot|ttf|otf)(?.*)?$/,
                    loader: 'url?limit=8192&context=client&name=[path][name].[hash:7].[ext]'
                },
                {
                    test: /.css$/,
                    loader: ExtractTextPlugin.extract('style', 'css'),
                },
                {
                    test: /.scss$/,
                    loader: ExtractTextPlugin.extract('style', 'css!sass')
                }]
    
    module.exports = productionConf
    

      

    基本跟开发的差不多,差别在于:

    1、使用ExtractTextPlugin 来打包css,所以要干掉原来base的loaders,重新写了一个,在最下面。

    2、UglifyJsPlugin 给js压缩代码。其他没有什么好解释的了,一样的。

    四、构建命令

    require('shelljs/global')
    env.NODE_ENV = 'production'
    var ora = require('ora')
    var webpack = require('webpack')
    var webpackConfig = require('./webpack.production.config')
    
    var spinner = ora('building for production...')
    spinner.start()
    
    var staticPath = __dirname + '/../public/dist/'
    rm('-rf', staticPath)
    mkdir('-p', staticPath)
    
    webpack(webpackConfig, function (err, stats) {
      spinner.stop()
      if (err) throw err
      process.stdout.write(stats.toString({
        colors: true,
        modules: false,
        children: false,
        chunks: false,
        chunkModules: false
      }) + '
    ')
    })
    

      

    写一个build.js,然后在package.json里面添加 script 参数

    "build": "node build.js"//这里记得写自己build.js路径

    甜点(马卡龙)--有点腻

    上面的配置是可以更改的,例如你在loaders 里面加上

    {
      test: /.vue$/,
      loader: 'vue'
    }
    

      

    就可以变成支持.vue文件的vuejs打包构建,同理,修改下支持jsx,和添加一些reactjs的module,就可以用来跑Reactjs的东西。

    还有可以随意更改Css预编译器的类型,用你自己喜欢就行,或者跟我们前面提到的方法,把所有类型都配置上,

    var path = require('path')
    var config = require('../config')
    var ExtractTextPlugin = require('extract-text-webpack-plugin')
    
    exports.assetsPath = function (_path) {
      return path.posix.join(config.build.assetsSubDirectory, _path)
    }
    
    exports.cssLoaders = function (options) {
      options = options || {}
      // generate loader string to be used with extract text plugin
      function generateLoaders (loaders) {
        var sourceLoader = loaders.map(function (loader) {
          var extraParamChar
          if (/?/.test(loader)) {
            loader = loader.replace(/?/, '-loader?')
            extraParamChar = '&'
          } else {
            loader = loader + '-loader'
            extraParamChar = '?'
          }
          return loader + (options.sourceMap ? extraParamChar + 'sourceMap' : '')
        }).join('!')
    
        if (options.extract) {
          return ExtractTextPlugin.extract('vue-style-loader', sourceLoader)
        } else {
          return ['vue-style-loader', sourceLoader].join('!')
        }
      }
    
      // http://vuejs.github.io/vue-loader/configurations/extract-css.html
      return {
        css: generateLoaders(['css']),
        postcss: generateLoaders(['css']),
        less: generateLoaders(['css', 'less']),
        sass: generateLoaders(['css', 'sass?indentedSyntax']),
        scss: generateLoaders(['css', 'sass']),
        stylus: generateLoaders(['css', 'stylus']),
        styl: generateLoaders(['css', 'stylus'])
      }
    }
    
    // Generate loaders for standalone style files (outside of .vue)
    exports.styleLoaders = function (options) {
      var output = []
      var loaders = exports.cssLoaders(options)
      for (var extension in loaders) {
        var loader = loaders[extension]
        output.push({
          test: new RegExp('\.' + extension + '$'),
          loader: loader
        })
      }
      return output
    }
    

      

    这就是把所有的css预编译的都加到配置里面了。

    总结下--买单啦

    Webpack多种多样,就算一个loaders都有好几种不同的配置,让人很是头疼,最关键的是很多插件自己的文档也不清不楚,弄得大家都很迷茫,我的经验就是多试多测,自己多写一写,看命令行打印的错误,去找原因,不要一看到报错就慌了,很多新手最容易犯错就是一看到报错就怀疑人生了,一定要看报错记录,一般都有提示,按照提示去解决相应问题就好啦。

    下一章我们讲Nodejs的东东。

  • 相关阅读:
    jquery选择器详解
    git discard when composer update
    ASCII码、HEX、字符、BCD 等等 基础知识思考
    中文汉字占二个字节还是三个字节长度
    php二分查找的两种实现方法
    windows下运行多个版本node.js
    NodeJS
    Error in library(qcc) : there is no package called 'qcc'
    jquery网络引用地址(收藏)
    实现二分查找
  • 原文地址:https://www.cnblogs.com/MonaSong/p/6544119.html
Copyright © 2011-2022 走看看