Webpack 入门教程

什么是 Webpack?

   Webpack是近期最火的一款模块加载器兼打包工具,它能把各种资源,例如JS(含JSX)、Coffee、样式(含Less/Sass)、图片等都作为模块来使用和处理。 
Webpack的优点

  1、支持CommonJS和AMD模块。
  2、支持很多模块加载器的调用,可以使模块加载器灵活定制,比如babel-loader加载器,该加载器能使我们使用ES6的语法来编写代码。
  3、可以通过配置打包成多个文件,有效的利用浏览器的缓存功能提升性能。
  4、开发便捷,它能有Grunt或Gulp所有基本功能。使用模块加载器,可以支持Sass、Less等处理器进行打包且支持静态资源样式及图片进行打包。
  5、内置有Source Map,即使打包在一起依旧方便调试。

入门教程:

入门Webpack,看这篇就够了:http://blog.csdn.net/kun5706947/article/details/52596766

30分钟手把手教你学webpack实战:http://www.cnblogs.com/tugenhua0707/p/4793265.html

Webpack 2 入门教程:https://gold.xitu.io/entry/583ffd1e61ff4b006b84daeb/?utm_medium=hao.caibaojian.com&utm_source=hao.caibaojian.com

Webpack 2 打包实战:https://github.com/fenivana/webpack-in-action

Webpack的安装与配置

  一、安装

  我们常规直接使用npm的形式来安装:

$ npm install webpack -g  # 全局安装

  当然如果常规项目还是把依赖写入package.json包去更人性化:

$ npm init  # 会自动生成一个package.json文件
$ npm install webpack --save-dev  # 将webpack增加到package.json文件中

  如果想要安装开发工具插件:

$ npm install webpack-dev-server --save-dev  # 自动刷新
$ npm install style-loader css-loader --save-dev  # 编译样式的插件

  二、配置

  每个项目下都必须配置有一个webpack.config.js ,它的作用如同常规的gulpfile.js/Gruntfile.js,就是一个配置项,告诉webpack它需要做什么。下面是一个例子:

var path = require("path");
var glob = require('glob');
var webpack = require('webpack');
var autoprefixer = require('autoprefixer');//添加浏览器供应商前缀
var HtmlWebpackPlugin = require('html-webpack-plugin'); //html模板生成器
var ExtractTextPlugin = require('extract-text-webpack-plugin'); //将你的行内样式提取到单独的css文件里
var CleanPlugin = require('clean-webpack-plugin'); //文件夹清除工具
var CopyWebpackPlugin = require('copy-webpack-plugin'); //文件拷贝

module.exports = {
    // devtool: 'eval-source-map', //配置生成Source Maps,利于排错和定位
    //插件项
    plugins: [
        //全局配置加载,使用ProvidePlugin加载使用频率高的模块
        new webpack.ProvidePlugin({
            $ : "jquery",
            jQuery : "jquery",
            "window.jQuery" : "jquery"
        }),
        // new CleanPlugin(['dist']),//清空dist文件夹
        //提公用js到common.js文件中
        new webpack.optimize.CommonsChunkPlugin({
            name: 'vendors', //将公共模块提取,生成名为'vendors'的chunk
            chunks: ['index','list','about'], //提取哪些模块共有的部分
            minChunks: 3 //提取至少3个模块共有的部分
        }), 
        //HtmlWebpackPlugin,模板生成相关的配置,每个对于一个页面的配置,有几个写几个
        new HtmlWebpackPlugin({ //根据模板插入css/js等生成最终HTML
            title: 'index', //用来生成页面的 title 元素
            // favicon: './src/img/favicon.ico', //favicon路径,通过webpack引入同时可以生成hash值
            filename: './view/index.html', //生成的html存放路径,相对于path
            template: './src/view/index.html', //html模板路径
            inject: 'body', //js插入的位置,true/'head'/'body'/false
            hash: true, //为静态资源生成hash值
            chunks: ['vendors', 'index'],//需要引入的chunk,不配置就会引入所有页面的资源
            minify: { //压缩HTML文件    
                removeComments: true, //移除HTML中的注释
                collapseWhitespace: false //删除空白符与换行符
            }
        }),
        new HtmlWebpackPlugin({ //根据模板插入css/js等生成最终HTML
            title: 'list', //用来生成页面的 title 元素
            // favicon: './src/img/favicon.ico', //favicon路径,通过webpack引入同时可以生成hash值
            filename: './view/list.html', //生成的html存放路径,相对于path
            template: './src/view/list.html', //html模板路径
            inject: true, //js插入的位置,true/'head'/'body'/false
            hash: true, //为静态资源生成hash值
            chunks: ['vendors', 'list'],//需要引入的chunk,不配置就会引入所有页面的资源
            minify: { //压缩HTML文件    
                removeComments: true, //移除HTML中的注释
                collapseWhitespace: false //删除空白符与换行符
            }
        }),
        new ExtractTextPlugin('css/[name].css'), //单独使用link标签加载css并设置路径,相对于output配置中的publickPath
        //压缩js代码
        new webpack.optimize.UglifyJsPlugin({    
            compress: {
                warnings: false
            },
            except: ['$super', '$', 'exports', 'require'] //排除关键字
        }),
        //拷贝图片
        // new CopyWebpackPlugin([
        //     {from: './src/images', to: './images'}
        // ]),
        //启用热模块更换
        new webpack.HotModuleReplacementPlugin()
    ],
    //使用webpack-dev-server,提高开发效率
    devServer: {
        contentBase: './',
        host: 'localhost',
        port: 9090, //默认8080
        inline: true, //可以监控js变化
        hot: true, //热启动
    },
    //页面入口文件配置,有几个写几个
    entry: {
        index: './src/js/page/index.js',
        list: './src/js/page/list.js'
    },
    //入口文件输出配置
    output: {
        path: path.join(__dirname, 'dist'), ////输出目录的配置,模板、样式、脚本、图片等资源的路径配置都相对于它(__dirname指根目录)
        filename: 'js/[name].[hash:6].js', //每个页面对应的主js的生成配置
        publicPath: '/dist/', //模板、样式、脚本、图片等资源对应的server上的路径
        chunkFilename: "js/[id].chunk.js" //chunk生成的配置
    },
    module: {
        //加载器配置,"-loader"其实是可以省略不写的,多个loader之间用"!"连接起来,根据从右到左的顺序依次调用加载器,前一个的输出是后一个的输入
        loaders: [
            {
                //.css文件使用style-loader、css-loader和postcss-loader来处理
                test: /.css$/, 
                loader: ExtractTextPlugin.extract("style-loader", "css-loader!postcss-loader")
            },
            {
                //.less文件使用css-loader、less-loader和postcss-loader来编译处理
                test: /.less$/, 
                loader: ExtractTextPlugin.extract("css!less!postcss")
            },
            {
                //.js文件使用json-loader来处理
                test: /.json$/, 
                loader: 'json'
            },
            {
                //HTML加载器,主要是加载模板使用的
                test: /.html$/, 
                loader: "html?attrs=img:src img:data-src" 
            },
            {
                //文件加载器,处理文件静态资源
                test: /.(woff|woff2|ttf|eot|svg)(?v=[0-9].[0-9].[0-9])?$/,
                loader: 'file-loader?name=./fonts/[name].[ext]'
            },
            {
                //.js文件使用babel-loader来编译处理,将es6转es5,排除node_modules目录下的文件, npm安装的包不需要编译
                test: /.js$/, 
                loader: 'jsx!babel?presets[]=es2015', 
                exclude: /node_modules/
            }, 
            {
                //图片文件使用url-loader来处理,小于8kb的直接转为base64
                test: /.(png|jpg|gif)$/, 
                loader: 'url-loader?limit=8192&name=images/[hash:8].[name].[ext]'
            }
        ]
    },
    postcss: function(){
        return [autoprefixer] //调用autoprefixer插件添加供应商前缀
    },
    //其它解决方案配置
    resolve: {
        //查找module的话从这里开始查找
        // root: [], //绝对路径
        //自动扩展文件后缀名,意味着我们require模块或import的时候可以省略不写后缀名
        extensions: ['', '.css', '.js', '.json', '.less']
        //模块别名定义,方便后续直接引用别名,无须多写长长的地址
        // alias: {
        //     a: './src/js/page/bind.js', //后续直接 require('a') 即可
        //     greet: './src/js/page/greeter.js'
        // }
    }
};

开发页面

index.js 内容如下:

//引入css
require('../../css/lib/normalize'); 
require('../../css/page/main'); 
require('../../css/page/myapp');

var greet = require('../../js/page/greeter.js');

let loader = require('../../js/page/bind.js');
console.log(loader);
document.getElementById('wrapper').appendChild(greet());
document.getElementById('container').innerText = 'APP';

//弹出提示框
$("#btn").on("click", function(){
    //webpack通过require.ensure来判断是否对资源进行按需加载
    require.ensure(["../../js/components/dialog"], function (require){
        var dialogModule = require('../../js/components/dialog');

        dialogModule();
    }); 
});

index.html 内容如下:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>index</title>
</head>
<body>
    <div id="wrapper">
        <div class="container" id="container"></div>
    </div>
    <button id="btn" type="button">提示框</button>
</body>
</html>

list.js 内容如下:

//引入css
require('../../css/lib/normalize'); 
require('../../css/page/main'); 

var slider = require('../../js/components/slider');
let loader = require('../../js/page/bind.js');
console.log(loader);

document.getElementById('container').innerText = 'APP';

//轮播图
slider();

list.html 内容如下:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>list</title>
</head>
<body>
    <div id="wrapper">
        <div class="container" id="container"></div>
    </div>
    <button id="btn" type="button">提示框</button>
    <br>

    <!--轮播区域-->
    <div id="bannerArea" class="banner">
        <div class="banner__img">
            <a href="javascript:"><img src="../images/1.jpg" width="100%" height="532" alt=""></a>
            <a href="javascript:"><img src="../images/2.jpg" width="100%" height="532" alt=""></a>
            <a href="javascript:"><img src="../images/3.jpg" width="100%" height="532" alt=""></a>
        </div>
        <ul class="banner__nav" id="bannerNav">
            <li class="selected">1</li>
            <li>2</li>
            <li>3</li>
        </ul>
    </div>
</body>
</html>

为了方便,我们通常将运行命令写在package.json中

"scripts": {
    "dev": "webpack-dev-server --progress --colors --hot --inline", //开发模式
    "build": "webpack -p" // 编译打包
 }

运行webpack

$ npm run build

通过webpack-dev-server实现自动刷新页面

$ npm run dev

只需要浏览器打开http://localhost:9090/dist/view/index.html即可看到效果,修改js、css代码保存后,页面自动刷新。

webpack常用命令:

$ webpack --config webpack.min.js   //另一份配置文件

$ webpack --display-error-details   //显示异常信息

$ webpack -w   //提供watch方法,实时进行打包更新
 
$ webpack -p    //对打包后的文件进行压缩
 
$ webpack -d    //提供SourceMaps,方便调试,告知哪些模块被最终打包到哪里了

webpack --colors   //输出结果带彩色,比如:会用红色显示耗时较长的步骤

webpack --profile   //输出性能数据,可以看到每一步的耗时

webpack --display-modules   //默认情况下 node_modules 下的模块会被隐藏,加上这个参数可以显示这些被隐藏的模块

实战教程:

Webpack实战项目:https://github.com/xiaoyunchen/easySlide

基于webpack的前端工程化开发之多页站点篇(一):https://github.com/vhtml/webpack-MultiPage-static

基于webpack的前端工程化开发之多页站点篇(二):https://github.com/vhtml/webpack-MultiplePage

Webpack之“多页面开发”最佳实战:http://www.duanliang920.com/learn/web353.html

原文地址:https://www.cnblogs.com/gyx19930120/p/6112571.html