@GivenCui
        
        2017-06-14T08:19:23.000000Z
        字数 7663
        阅读 897
    webpack
a) js的模块打包(module bundler)工具, Code Splitting代码分割,实现按需加载,也可以加载各种资源(loader)
b) 兼容AMD,CommonJS(Node),ES6模块语法
c) 部分自动化任务,如热更新, 压缩等
入口(entry) 
输出(output) 
loader 
插件(plugins)
# 当前目录右键打开git-bash$ mkdir webpack-test$ cd webpack-test$ npm init -y$ npm install webpack --save-dev / yarn add webpack -D/--dev# 用atom编辑器打开当前目录$ atom ./
/* Node的CommonJS模式 */// hello.jsvar world = require('./world');function hello () {}// world.jsfunction world (){}module.exports = world;
/* ES6的module模式 不用安装babel也支持 */// hello.jsimport world from './world'; // ES6function hello(arg) {console.log(arg);}hello(world.msg());// world.jsfunction world() {return 'hello world new';}export default { // ES6msg : world};
# 把hello.js -打包-> hello.bundle.js$ webpack hello.js hello.bundle.js
// hello.js// css-loader处理.css文件// 然后style-loader插入到head的<style></style>// index.html中F12可以查看// !为分隔符, 从路径中源从右向左经过loaderrequire('style-loader!css-loader!./style.css');//方法二:// hello.jsrequire('./style.css') // loader加载器在命令行中引用# cli中# 查看webpack命令行参数$ webpack -h# --module-bind参数指的loader$ webpack hello.js hello.bundle.js --module-bind 'css=style-loader!css-loader' --watch --progress --display-modules --display-reasons# --watch自动打包, 但还需要主动F5刷新# --progress 打包进度# --display-modules 显示打包模块# --display-reasons 显示打包原因
$ mkdir webpack-demo$ cd webpack-demo$ npm init -y$ yarn add webpack -D$ mkdir src$ mkdir dist$ touch index.html$ touch webpack.config.js$ touch webpack.mul.config.js$ cd src$ mkdir script // 源文件可能为js,JSX, ES6, CoffeeJS$ mkdir style // 源文件可能为css,less,sass$ cd ./dist$ mkdir css$ mkdir js
// webpack.config.jsconst HtmlWebpackPlugin = require('html-webpack-plugin'); //installed via npmconst webpack = require('webpack'); //to access built-in pluginsconst path = require('path'); // node APImodule.exports = { // node的CommonJs模块规范entry: './src/script/main.js', // 入口output: { // 出口path: path.resolve(__dirname, 'dist'), // node中方法// path: __dirname + '/dist/js' // 等价写法// path: './dist/js' // erro: 必须写绝对路径filename: 'bundle.js'},module: { // loaderrules: [{test: /\.(js|jsx)$/, use: 'babel-loader'}]},plugins: [ // 插件new webpack.optimize.UglifyJsPlugin(),new HtmlWebpackPlugin({template: './src/index.html'})]};
# webpack.config.js是默认配置文件$ webpack# --config运行自定义配置文件$ webpack --config webapck.dev.config.js# 写在package.js的scripts中"scripts": {"webpack":"webpack --config webpack.dev.config.js --progress --display-modules --colors --display-reasons"}$ npm run webpack
entry: 如果传入一个字符串或字符串数组,chunk 会被命名为 main。如果传入一个对象,则每个键(key)会是 chunk 的名称,该值描述了 chunk 的入口起点
output:
// webpack.config.jsconst path = require('path'); // node APImodule.exports = {entry : './src/script/main.js',output : {path: path.resolve(__dirname,'dist/js'), // 有二种写法filename:'bundle.js'}}
对比发现main.js和vendors.js的runtime是重复的
适合多页面应用程序中,如PC端
output中的[chunkhash]非常有用, 用于上线的缓存问题
// webpack.config.jsconst path = require('path'); // node APImodule.exports = {entry : { // 多个chunksmain : './src/script/main.js',vendors: './src/script/vendors.js'},output : {path: path.resolve(__dirname,'dist/js'), // 有二种写法filename:'[name].js'// 占位符(模板字符串):// [name] 对应entry中的key (chunk name)// [hash] 模块标识符(module identifier)的 hash, 打包一次变一次// [chunkhash] 对应文件的md5值, 文件改变chunkhash才变}}
const path = require('path');module.exports = {// page1.js和page.js之间并列, 彼此没有依赖关系// bundle.js中有multi模块处理,把page1,2合并entry : ['./src/script/page1.js', './src/script/page2.js'],output : {path : path.resolve(__dirname,'dist/js'),filename : 'bundle.js',}}
html-webpack-plugin可以自动生成index.html,可压缩,去注释等
插件都是构造函数, 用时需要实例化
html-webpack-plugin输出index.html的路径参考output
该插件可以指定参考模板
# 安装$ yarn add html-webpack-plugin -D// webpack.config.jsconst path = require('path');const HtmlWebpackPlugin = require('html-webpack-plugin');module.exports = {entry:{ // 多入口情况, 对应MPA(多页应用),多个chunksmain : './src/script/main.js',vendors: './src/script/vendors.js'},output: {filename: '[name]-[chunkhash].js', // 可以使用相对路径path: path.resolve(__dirname, 'dist/js') // 路径对插件也有影响},plugins:[// new HtmlWebpackPlugin() // 默认情况new HtmlWebpackPlugin({filename: '../index.html', // 在这里更改相对路径template:'index.html',// inject:'head' // js插到head中title:'Webpack is awesome',date: new Date()})]};
<%= %>和 <% %>
// index.js (插件参考模板)<!DOCTYPE html><html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><!-- 取值插件中的title设置 --><title><%=htmlWebpackPlugin.options.title%></title></head><body><p><%= htmlWebpackPlugin.options.date %></p> // 获取的了date</body></html>
更改成绝对路径
压缩代码
const path = require('path');const HtmlWebpackPlugin = require('html-webpack-plugin');module.exports = {entry:{main : './src/script/main.js',vendors: './src/script/vendors.js'},output: {filename: '[name]-[chunkhash].js',path: path.resolve(__dirname, 'dist/js'),publicPath:"http://cdn.example.com/assets/" // 线上发布的绝对路径},plugins:[new HtmlWebpackPlugin({filename: '../index.html',template:'index.html',minify:{ // 配置压缩对象参数collapseWhitespace:true,removeComments:true}})]};// 命令行中: webpack --config webpack.mul.config.js
new HtmlWebpackPlugin()对应一个新的html页面
通过chunks和excludeChunks参数控制引入脚本
需求: 部分chunk以内部script写在head标签中 
html-webpack-inline-source-plugin
const path = require('path');const HtmlWebpackPlugin = require('html-webpack-plugin');module.exports = {entry:{main : './src/script/main.js',a:'./src/script/a.js',b:'./src/script/b.js',c:'./src/script/c.js'},output:{path:path.resolve(__dirname,'dist/js'),filename:'[name]-[chunkhash].js',// publicPath:'http://cdn.com'},plugins:[new HtmlWebpackPlugin({filename:'../a.html',template:'index.html',title:'A page',// chunks:['main','a'], // 引入chunkexcludeChunks:['b','c'] // 排除的chunk}),new HtmlWebpackPlugin({filename:'../b.html',template:'index.html',title:'B page',// chunks:['main','b']excludeChunks:['a','c']}),new HtmlWebpackPlugin({filename:'../c.html',template:'index.html',title:'C page',chunks:['main','c']})]}
// 演示目录结构src---componets||---layerlayer.htmllayer.jslayer.lessapp.js
loader 用于对模块的源代码进行转换。loader 可以使你在 require() 或"加载"模块时预处理文件
使用方法 
1. 在webpack.config.js中配置module.rules  
2. 在 require 语句中显示使用 
3. 同过CLI
// 1.webpack.config.js中配置// 三种写法等价module.exports = {module: {rules: [{test: /\.css$/, loader: 'style-loader!css-loader'} // v1.0写法// or equivalently{test: /\.css$/, use: ['style-loader','css-loader']} // 推荐// or equivalently{test: /\.css$/, use: [{loader:'style-loader',options: {}},{ // 推荐loader: 'css-loader',options: {}}}]}};// 举例// use的执行顺序是从右往左从下到上module: {rules: [{test: /\.css$/,use: [{ loader: 'style-loader'},{loader: 'css-loader',options: {modules: true}}]}]}// 2. 在 require 语句中显示使用require('style-loader!css-loader?modules!./styles.css');# 3. 同过CLI$ webpack --module-bind jade-loader --module-bind 'css=style-loader!css-loader'
Babel官网 
webpack Babel-loader API
# 安装$ yarn add babel-loader babel-core babel-preset-env babel-preset-stage-2 -D// webpack.config.jsmodule: {rules: [{test: /\.js$/,exclude:path.resolve(__dirname, 'node_modules'), // 排除范围include: path.resolve(__dirname, 'src'),, // 限定范围,注意是绝对路径use: {loader: 'babel-loader'}}]}// .babelrc{"presets": ["env","stage-2"],"plugins": []}
# 安装$ yarn add style-loader css-loader -D// webpack.config.jsmodule:{rules:[{test:/\.css$/,use:[ 'style-loader', 'css-loader' ]}]}
配合相关插件完成自动添加前缀,
webpack postcss-loader API 
postcss-loader 
browserslist string (autoprefixer配置用)
# 安装$ yarn add postcss-loader autoprefixer -Dmodule : {rules : [{test:/\.css$/,use:['style-loader',{loader: 'css-loader',options: { importLoaders: 1 }},'postcss-loader']}]}
// postcss.config.jsmodule.exports = {plugins: [require('autoprefixer')({browsers: ['last 4 version']})]}