深入学习webpack

webpack配置是标准的Node.js CommonJS模块,webpack中的绝对路径指"/src/css/file",相对路径指"../css/file"。

温馨提示:本篇文章立足于3.5.x版本。

一、入口,entry
entry值可以是字符串,数组,对象。

//写法1是写法2的简写
const config = {
  entry: './src/file1.js'
};

//写法2
const config = {
  entry: {
    main: './src/file1.js'
  }
};

const config = {
  entry: ['./src/file1.js','./src/file2.js']
};

const config = {
  entry: {
    main: './src/file1.js',
    app: './src/file2.js'
  }
};

二、输出,output

const config = {
  output: {
    filename: 'bundle.js',
    path: '/dist'
  }
};

webpack有多种占位符,常见的如下:
[name]:代表打包后文件的名称,在entry或代码中确定;
[id]:webpack给块分配的内部chunk id,如果你没有隐藏,可以在打包后的命令行中看到;
[hash]:每次构建过程中,生成的唯一hash值;
[chunkhash]:依据于打包生成文件内容的hash值,内容不变,值不变。

三、模块,Modules
webpack模块有以下几种方式表达依赖关系:
1、ES2015 import;
2、同步,CommonJS require;
3、异步,AMD define和require语句;
4、css/less/sass中的@import;
5、样式中的url(...)和html文件中的<img src="..."/>。

四、加载器,loaders

loader是运行在Node.js中的函数,可以将资源文件作为参数,返回新的资源文件。loader用于加载某些资源文件,因为webpack本身只能打包CommonJS规范的js文件,对于其他资源,例如css,图片等,是没有办法加载的,这就需要对应的loader将资源转换。

1、babel-loader
加载ES2015+代码,然后使用Babel转译为ES5。

// npm一次性安装多个依赖模块,模块之间用空格隔开
npm install --save-dev babel-core babel-loader babel-preset-es2015 
npm install --save-dev babel-loader babel-core babel-preset-env webpack
//单独配置.babelrc文件
module: {
  rules: [
    {
      test: /\.js$/,
      exclude: /(node_modules|bower_components)/,
      use: {
        loader: 'babel-loader',
        options: {
          presets: ['env'],
          plugins: [require('babel-plugin-transform-object-rest-spread')]
        }
      }
    }
  ]
}

2、css-loader
解析css文件后,使用import加载,并且返回css代码。

npm install --save-dev css-loader
import css from 'file.css';
module: {
  rules: [
    {
      test: /\.css$/,
      use: [ 'style-loader', 'css-loader' ]
    }
  ]
}

3、style-loader
将模块的导出作为样式添加到DOM中。

npm install style-loader --save-dev
import style from './file.css';
module: {
  rules: [
    {
      test: /\.css$/,
      use: [
        { loader: "style-loader" },
        { loader: "css-loader" }
      ]
    }
  ]
}

4、sass-loader

加载sass文件。

#安装sass-loader
npm i -D node-sass sass-loader css-loader
//webpack.config.js
module.exports={
  module:{
    rules:[
      {
        test:/\.scss$/,
        use:[
          "style-loader",
          "css-loader",
          "sass-loader"
        ]
      }
    ]
  }
}
//index.js,自动编译成css
require "./main.scss"

5、postcss-loader
使用postcss加载和转译css/sss文件。

npm i -D  postcss-loader
//postcss.config.js
module.exports = {
  parser: 'sugarss',
  plugins: {
    'postcss-import': {},
    'postcss-cssnext': {},
    'autoprefixer': {},
    'cssnano': {}
  }
}
//webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          'style-loader',
          { loader: 'css-loader', options: { importLoaders: 1 } },
          'postcss-loader'
        ]
      }
    ]
  }
}

6、url-loader
像file loader一样工作,但如果文件小于限制,可以返回data URL。

npm install --save-dev url-loader
import img from './image.png';
  module: {
    rules: [
      {
        test: /\.(png|jpg|gif)$/,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 8192
            }
          }
        ]
      }
    ]
  }

7、file-loader
将文件发送到输出文件夹,并返回(相对)URL。

npm install --save-dev file-loader
import img from './file.png';
  module: {
    rules: [
      {
        test: /\.(png|jpg|gif)$/,
        use: [
          {
            loader: 'file-loader',
            options: {
              name: '[path][name].[ext]?[hash]'
            }
          }
        ]
      }
    ]
  }

8、html-loader
导出html为字符串,需要引用静态资源。

npm i -D html-loader
module: {
  rules: [{
    test: /\.html$/,
    use: [ {
      loader: 'html-loader',
      options: {
        minimize: true
      }
    }]
  }]
}

五、插件,plugins
webpack插件是一个具有apply属性的JavaScript对象,apply属性会被webpackcompiler调用,并且compiler对象可在整个compilation生命周期访问。plugin用于扩展webpack的功能,直接作用于webpack。

1、内置插件

A、BannerPlugin
为每个chunk文件头部添加注释信息。

new webpack.BannerPlugin(str)

B、CommonsChunkPlugin
它从根本上允许我们从不同的bundle中提取所有的公共模块,并且将他们加入公共bundle中。如果公共bundle不存在,那么它将会创建一个出来。
如果有任意模块加载了两次或更多(通过minChunks设置该值),它就会被打包进一个叫commons.js的文件里,后面你就可以在客户端缓存这个文件了。当然,这肯定会造成一次额外的请求,但是却避免了客户端多次下载相同库的问题。这个带来速度上的提升,因为浏览器会迅速将公共的代码从缓存中取出来,而不是每次访问一个新页面时,再去加载一个更大的文件。

new webpack.optimize.CommonsChunkPlugin({
  name: "manifest",
  minChunks: Infinity
})

C、DefinePlugin
创建一个在编译时可配置的全局常量,如果你自定义了一个全局变量PRODUCTION,可在此设置其值来区分开发还是生产环境,是启动dev server或者是prod server。

new webpack.DefinePlugin({
  'process.env.NODE_ENV': JSON.stringify('production') // or development
})

D、EnvironmentPlugin
实际上是DefinePlugin插件中对process.env进行设置的简写形式,如new webpack.EnvironmentPlugin(['NODE_ENV', 'DEBUG']) 将设置process.env.NODE_ENV='DEBUG'

E、UglifyJsPlugin
压缩JS代码。

const webpack = require('webpack');
 
module.exports = {
  plugins:[
    new webpack.optimize.UglifyJsPlugin({
      sourceMap: options.devtool && (options.devtool.indexOf("sourcemap") >= 0 || options.devtool.indexOf("source-map") >= 0)
    })
  ]
}

F、UglifyjsWebpackPlugin

npm i -D uglifyjs-webpack-plugin
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');

module.exports = {
  plugins: [
    new UglifyJSPlugin()
  ]
}

G、HotModuleReplacementPlugin
启用热替换模块(Hot Module Replacement),也被称为HMR,永远不要在生产环境(production)下启用HMR。

new webpack.HotModuleReplacementPlugin()

H、ProvidePlugin

自动加载模块,不要import或者require引入。

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

2、非内置插件

A、ExtractTextWebpackPlugin
代码拆分,分离css和js文件。它将所有的入口chunk中引用的 *.css,移动到独立分离的css文件,使得样式不再内嵌到jsbundle中,而是会放到一个单独的css文件(即styles.css)当中。如果你的样式文件大小较大,这会做更快提前加载,因为css bundle会跟js bundle并行加载。

npm install --save-dev extract-text-webpack-plugin
const ExtractTextPlugin = require("extract-text-webpack-plugin");

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ExtractTextPlugin.extract({
          fallback: "style-loader",
          use: "css-loader"
        })
      }
    ]
  },
  plugins: [
    new ExtractTextPlugin("styles.css")
  ]
}

B、HtmlWebpackPlugin

这个插件的作用是依据一个简单的index.html模板,生成一个自动引用你打包后的JS文件的新index.html,在每次生成的js文件名称不同时非常有用(比如添加了hash值)。

npm install --save-dev html-webpack-plugin
var HtmlWebpackPlugin = require('html-webpack-plugin');
var webpackConfig = {
  entry: 'index.js',
  output: {
    path: 'dist',
    filename: 'index_bundle.js'
  },
  plugins: [new HtmlWebpackPlugin()]
};
module.exports = webpackConfig;

C、CompressionWebpackPlugin
使用配置的算法(如gzip)压缩打包生成的文件。

npm i -D compression-webpack-plugin
var CompressionPlugin = require("compression-webpack-plugin");
module.exports = {
  plugins: [
    new CompressionPlugin({
      asset: "[path].gz[query]",
      algorithm: "gzip",
      test: /\.(js|html)$/,
      threshold: 10240,
      minRatio: 0.8
    })
  ]
}

D、visualizer和stats

webpack的可视化插件

const StatsWriterPlugin = require('webpack-stats-plugin').StatsWriterPlugin;
const Visualizer = require('webpack-visualizer-plugin');

module.exports = {
    ...
    plugins: [
        new StatsWriterPlugin({
            fields: null,
            stats: {
                chunkModules: true
            }
        }),
        new Visualizer({
            filename: './statistics.html'
        }),
        ...
    ]
}

六、devtool

// 以牺牲构建速度为代价,但是map表最详细。
devtool: "source-map"

// 嵌入到源文件中,为打包前的每一个文件添加sourcemap的DataUrl,DataUrl是包含一个文件完整souremap信息的Base64格式化后的字符串,而不是一个 url。
devtool: "inline-source-map"

// 没有模块映射,而是命名模块,以牺牲细节达到最快。
devtool: "eval" 

// 将SourceMap嵌入到每个模块中
devtool: "eval-source-map"

// SourceMap不在源文件中引用
devtool: "hidden-source-map"

//没有模块映射
devtool: "cheap-source-map"

//有模块映射
devtool: "cheap-module-source-map"

当webpack打包源代码时,可能会很难追踪到错误和警告在源代码中的原始位置。JavaScript提供了source map功能,将编译后的代码映射回源代码,使调试更容易。如果一个错误来自于b.js,source map就会明确的告诉你。

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');

  module.exports = {
    entry: {
      app: './src/main.js',
      print: './src/sec.js'
    },
+   devtool: 'inline-source-map',
    plugins: [
      new CleanWebpackPlugin(['dist']),
      new HtmlWebpackPlugin({
        title: 'Development'
      })
    ],
    output: {
      filename: '[name].bundle.js',
      path: path.resolve(__dirname, 'dist')
    }
  };

假设在sec.js中写一个错误语法,编译打包后,刷新页面,就会在控制台看到错误文件及出错行数。

七、devServer
用于设置webpack-dev-server的命令行。

devServer: {
  bonjour:true,
  contentBase: path.join(__dirname, "dist"),
  compress: true,
  historyApiFallback: true, 
  hot: true, 
  inline: true,
  open:true
}

看了那么多文档,一般都是清一色的英文,这次竟然发现devServer的属性值中有bonjour,哈哈,挺好的,我猜写webpack的开发人员会点法语。

//webpack.config.js

const path = require('path');
module.exports = {
  entry:"",
  output: {
    path: path.resolve(__dirname, "dist"), //路径解析
    filename: "bundle.js"
  },
  module: {
    rules: []
  },
  plugins: [],
  devtool: "inline-source-map",
  devServer: {
    contentBase: "./public", //本地服务器所加载的页面所在的目录
    historyApiFallback: true, //不跳转
    inline: true, //实时刷新
    stats:{}
  },
  target:"web",
  externals: {
    vue: 'vue'
  },
  performance: {
    hints: "error" //生产环境推荐用error,开发环境推荐用warning
  }
}

 

转载于:https://www.cnblogs.com/camille666/p/webpack_deep_learning.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值