tool - Webpack

基本

webpack 是以 commonJS 的形式来书写的,但对 AMD/CMD 的支持也很全面。

什么是 commonJS 规范?《点击查看》

webpack 的配置文件 webpack.config.js 主要分为三大块:

  • entry - 入口文件 让 webpack 用哪个文件作为项目的入口
  • output - 出口 让 webpack 把处理完成的文件放在哪里
  • module - 模块 要用什么不同的模块来处理各种类型的文件

安装

mkdir  forwebpack

cd     forwebpack

npm    init                              // 创建package.json

sudo npm install webpack --save-dev

--save                                   // 将安装信息放入package.json的dependencies(产品模式)

—save-dev                                // 将安装信息放入package.json的devDependencies(开发模式)

入口起点(Entry)

entry:(可以是数组)这里我们使用的 entry.jsentry 下的路径。index 可能是将来生成的文件名。index.js 注:如果 outputfilename 是有名称的则会使用 filename 来命名,否则使用自身的名称

单个入口(简写)语法

const config = {
    entry: './path/to/my/entry/file.js'
}

对象语法

const config = {
  entry: {
    app: './src/app.js',
    vendors: './src/vendors.js'
  }
};

输出(Output)

output:让 webpack 把处理完成的文件放在哪里

  • path - 输出的路径
  • filename - 定义输出的文件名称(支出数组 【name】,根据入口文件的 entry 的数量)

加载器(Loaders)

module 加载器:将用到的文件处理后再输出

  • -loader 可以省略不写,多个 loader 之间用 ! 连接

  • loader 是需要安装的 sudo npm install *-loader —save-dev

module 中可以是使用 module.rules 配置 loader 也可以通过 module.loaders 进行配置。(在 < 4的webpack版本中) webpack-v4.0以上的还未进行尝试

 module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          { loader: 'style-loader'},
          {
            loader: 'css-loader',
            options: {
              modules: true
            }
          }
        ]
      }
    ]
  }

Loader特性

  • loader 支持链式传递。能够对资源使用流水线(pipeline)。loader 链式地按照先后顺序进行编译。loader 链中的第一个 loader 返回值给下一个 loader。在最后一个 loader,返回 webpack 所预期的 JavaScript。
  • loader 可以是同步或异步函数。
  • loader 运行在 Node.js 中,并且能够执行任何可能的操作。
  • loader 接收查询参数。用于 loader 间传递配置。
  • loader 也能够使用 options 对象进行配置。
  • 除了使用 package.json 常见的 main 属性,还可以将普通的 npm 模块导出为 loader,做法是在 package.json 里定义一个 loader 字段。
  • 插件(plugin)可以为 loader 带来更多特性。
  • loader 能够产生额外的任意文件。

工程目录:

| - dist
    | - src
    | - fn
        | - *.js
| - node_modules
| - src
    | - fn
        | - *.js
| - plugin
| - style
    | - *.css
| - view
    | *.html
| - .gitignore
| - package.json
| - webpack.config.js

webpack.config.js配置文件

var webpack           = require('webpack');
var commonsPlugin     = new webpack.optimize.CommonsChunkPlugin('common.js');
var path              = require('path');
var HtmlwebpackPlugin = require('html-webpack-plugin');

// 定义了一些文件夹的路径
var ROOT_PATH   = path.resolve(__dirname);
var APP_PATH    = path.resolve(ROOT_PATH, 'src/fn/entry.js');
var BUILD_PATH  = path.resolve(ROOT_PATH, 'dist/src/fn');

module.exports = {
    // 插件项
    plugins: [
        commonsPlugin,
        new HtmlwebpackPlugin({
        title: 'Hello World app'
    })
    ],
    // 页面入口文件配置
    entry: {
        // 支持数组形式,将加载数组中的所有模块,但以最后一个模块作为输出
        // index : './src/js/page/index.js'
        index: APP_PATH
    },
    // 入口文件输出配置
    output: {
        path: BUILD_PATH,
        filename: '[name].js'
    },
    module: {
        // 加载器配置,loader的处理顺序 右到左
        loaders: [
            // .css 文件使用 style-loader 和 css-loader 来处理
            { test: /\.css$/, loader: 'style-loader!css-loader'},
            // .js 文件使用 jsx-loader 来编译处理
            { test: /\.js$/, loader: 'jsx-loader?harmony' },
            // .scss 文件使用 style-loader、css-loader 和 sass-loader 来编译处理
            { test: /\.scss$/, loader: 'style!css!sass?sourceMap'},
            // 图片文件使用 url-loader 来处理,小于8kb的直接转为base64
            { test: /\.(png|jpg)$/, loader: 'url-loader?limit=8192'}
        ]
    },
    // 其它解决方案配置
    resolve: {
        // 查找module的话从这里开始查找
        root: '/Users/lijiahao/projects/forWebpack',           // 绝对路径
        // 自动扩展文件后缀名,意味着我们 require 模块可以省略不写后缀名
        extensions: ['', '.js', '.json', '.scss','css'],
        // 模块别名定义,方便后续直接引用别名,无须多写长长的地址
        alias: {
            AppStore : 'js/stores/AppStores.js',                // 后续直接 require('AppStore') 即可
            ActionType : 'js/actions/ActionType.js',
            AppAction : 'js/actions/AppAction.js',
            indexCss: './style/index.css'
        }
    },
    devServer: {
        historyApiFallback: true,
        hot: true,
        inline: true,
        progress: true
    }
};

webpack 文件详解

入口文件entry.js:

require 相关的文件

require('./module1');
require('../../style/main.css');
require('./common.js');
require('./index.js');

其他文件:

common.js

console.log('hello world!');

index.js

var $ = require('jquery');

;(function () {
    var test = {
        init: function () {
            this.addEvent();
        },
        addEvent: function () {
            this.time = this.getTime();
            var that = this;
            setInterval(function () {
                that.time = that.getTime();
                $('body').html('<div class="time">'+that.time+'</div>');
            },500)
        },
        getTime: function () {
            var date = new Date();
            var minutes = date.getMinutes();
            var seconds = date.getSeconds();

            if( minutes < 10 ){
                minutes = '0' + minutes
            }
            if( seconds < 10 ){
                seconds = '0' + seconds
            }

            return date.getFullYear() + '-' + (date.getMonth() + 1) + '-' + date.getDate() + ' ' + date.getHours() + ':' + minutes + ':' + seconds;
        }
    };
    $(function () {
        test.init()
    });
})();

module1.js

// 修改module1.js
require(["./module3"], function(){
    console.log("Hello Webpack!");
});

module2.js

// module2.js,使用的是CommonJs机制导出包
module.exports = function(a, b){
    return a + b;
}

module3.js

// module3.js,使用AMD模块机制
define(['./module2.js'], function(sum){
    return console.log("1 + 2 = " + sum(1, 2));
})

main.css

body{
    background: red;
    color: white;
}

运行webpack

在命令行内输入webpack 或者 webpack —display-error-details(出错时能查阅更详尽的信息)

其他有用的指令:

- webpack -—config *.js  // 使用另外一份config文件在打包
- webpack —watch         // 监听变动自动打包
- webpack -p             // 压缩混淆脚本
- webpack -d             // 生成map映射文件,告知哪些模块被最终打包到哪里了

相关插件介绍:

1.CommonsChunkPlugin

功能介绍:提取入口文件的公共脚本部分,然后生成一个 *.js 在方面多页面之间的复用

配置:

var commonsPlugin     = new webpack.optimize.CommonsChunkPlugin(‘【name.js');
plugin: [
     commonsPlugin
]

2.html-webpack-plugin

功能介绍:自动快速生成HTML

安装:

sudo npm install html-webpack-plugin —save-dev

配置:

plugins: [
     new HtmlwebpackPlugin({
          title:''
     })
]

3.webpack-dev-server

功能介绍:server服务器代理,代码变动时候自动编译并且刷新浏览器

安装:

sudo npm install webpack-dev-server —save-dev

配置:

devServer: {
     historyApiFallback: true,
     hot: true,
     inline: true,
     progress: true
}

再在package.json里面配置

"scripts": {
  "start": "webpack-dev-server --hot --inline"
},

然后输入npm start 在游览器里面输入localhost:8080。

SPA

既然常用 webpackReact 一类的 SPA,那么一个典型的例子就是前后端分离。

后端是一个 RESTfulserver 不管用什么写的。

假定在本机他是类似 http://localhost:8080/api/* 这类的请求,现在添加配置让 ajax 请求可以直接 proxy 过去。

// 其实很简单的,只要配置这个参数就可以了
proxy: {
'/api/*': {
    target: 'http://localhost:8080',
    secure: false
    }
}

4.第三方库 如 jqueryunderscoremomnetzepto

安装:

sudo npm install jquery —save-dev

5.ProvidePlugin

功能:将全局变量插入到所有代码中。

配置:

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

    })

6.import-loader

安装:

sudo npm install import-loader —save-dev
// 注意这种写法 我们把 `jQuery` 这个变量直接插入到 `plugin.js` 里面了
// 相当于在这个文件的开始添加了 `var jQuery = require('jquery')`;

import 'imports?jQuery=jquery!./plugin.js';

7.添加 es6 的支持(未做)

8.jshint-loader

功能:检查代码规范

安装:

sudo npm install jshint-loader —save-dev
// 和loaders一样的语法,很简单
perLoaders: [
     {
     test: /\.jsx?$/,
     include: APP_PATH,
      loader: 'jshint-loader'
      }
]
// 配置jshint 支持es6校验。
jshint: {
  "esnext": true

},

启动:

npm run start

todo

  • >=webpack4.0

其他

链接: