如何使用Webpack进行打包?

一、理解Webpack的打包过程

1.创建一个test目录并进入

mkdir test && cd test  
  1. npm 初始化,生成package.json文件
npm init -y  //如果不加-y就一路回车
  1. 安装webpack
npm install webpack --save-dev   //会安装到test目录下node_modules目录下面

4.在根目录下新建一个hello.js文件并用webpack进行打包

touch hello.js 
./node_modules/.bin/webpack hello.js hello.bundle.js

这样就完成了一次最简单的打包,./node_modules/.bin/webpack就是安装在test目录下的webpack命令。虽然完成了一次极简的打包,但是这样是远远不够的。

5.试着多添加一个world.js文件

world.js

export { world }   //写一个函数并将它暴露出来
function world() {
  alert('我是world')
}

hello.js内容

require('./world.js')  //引入world.js
world() 在hollo.js中执行world.js中的函数

运行打包命令

./node_modules/.bin/webpack hello.js hello.bundle.js

成功打包。这样,hello.js就是入口文件,其它文件诸如world.js都通过ES6/Commom.js/AMD语法引入到这个入口文件里,然后打包成一个文件hello.bundle.js文件。这样,就可以实现模块化编程,不仅仅是JS文件,CSS、SASS、LESS、VUE等都可以引入到入口文件里,再进行打包,这就是模块化,而需要做的,就是安装针对不同类型的loader。

二、配置文件

上面写的内容主要是理解,接下来为了更好地发挥webpack的功能,我们重新整理和配置webpack的文件

1. 删除之前根目录下除了node_modules和json文件之外的所有其它文件。
2. 在test目录下新建src目录,所有的源码都放在这里,在src目录下,分别新建script目录和style目录用来存放
js文件和样式文件。

3. 在test目录下新建dist目录,作为打包以后的输出文件的存放目录。
4. 在test目录下新建index.html文件,用script标签引入dist/bundle.js文件。
5. 在test目录下新建webpack.config.js作为配置文件。

三、配置webpack.config.js

webpack.config.js是webpack的配置文件,在我们运行webpack打包命令的时候,它会自动去寻找这个文件,然后根据这个文件里的具体配置来进行打包。

  1. webpack.config.js内容
var path = require('path')                                      //引入path

module.exports = {                                              //注意这里是exports不是export
  entry: './src/script/main.js',                                 //入口文件
  output: {                                                       //输出文件
    path: path.resolve(__dirname,'dist'),                      //输出文件的目录
    filename: 'bundle.js'                                        //输出文件的名称
  }
}

运行打包命令

./node_modules/.bin/webpack                     //有了配置文件以后直接输入命令即可,它会自动找配置文件

如果我们有多个配置文件,比如还有一个webpack.dev.config.js文件,webpack默认运行的文件是webpack.config.js,但是想要让它运行另一个配置文件应该怎么办呢?办法如下:

./node_modules/.bin --config webpack.dev.config.js               //使用--config参数就行了

这里还有一个问题,就是每次运行webpack命令,都要写./node_modules/.bin/webpack这样一长串,可不可心简化呢?当然是可以的。只需要package.json文件里写一个script就行了。

屏幕快照 2017-08-18 上午12.03.43.png

这样,只要我们运行npm build就相当于执行了webpack命令,而npm会非常智能地从node_modules里找这个命令。
当然,这个命令还可以继续优化。我们发现,每次打包以后,bundle.js的文件都会非常大,如果让它变小呢?那就使用./node_modules/.bin/webpack -p这个命令 -p就是出版的意思,这样它就会自动压缩,所以我再改一下package.json文件。

屏幕快照 2017-08-18 上午12.09.08.png

这样,再次运行npm run build就相当于运行了./node_modules/.bin/webpack -p了。我们可以明显地发现,bundle.js的体积被压缩了。

  1. 运行打包命令时可以使用的其它参数
./node_modules/.bin/webpack --progress --display-modules --display-reason --colors  //看到过程、显示模块、显示打包原因、看到颜色变化
四、多页面进行打包时webpack.config.js的配置方法
var path = require('path')

module.exports = {                            //注意这里是exports不是export
  entry: {                                             //这里entry写成了对象,这样的话就可以写多个入口文件分别打包
    main: './src/script/main.js',       
    a: './src/script/a.js'
  },
  output: {
    path: path.resolve(__dirname,'dist'),
    filename: '[name]-[hash]-bundle.js'                  //这里[name]-[hash]-bundle.js通过name和hash来区分不同的
  }
}

这样的话,就可以把多个入口文件打包成不同文件名和不同哈希值的JS文件,并且都放在dist目录下。

但是这里却有一个很大的问题,那就是每次打包都会新生成一次打包文件,这些文件如何放到HMTL里呢?总不能每打一次包就手动更改一次吧?为了解决这个问题,就需要使用一个插件:html-webpack-plugin。用这个插件动态生成HTML文件并且把相应的打包文件放到里面。

npm安装插件

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

改写webpack.config.js文件:

var path = require('path')
var HtmlWebpackPlugin = require('html-webpack-plugin')                //Common.js语法引入插件

module.exports = {             //注意这里是exports不是export
  entry: {
    main: './src/script/main.js',
    a: './src/script/a.js'
  },
  output: {
    path: path.resolve(__dirname,'dist'),
    filename: '[name]-[hash]-bundle.js'
  },
  plugins: [                                             //使用插件
    new HtmlWebpackPlugin({                              //因为要生成两个不同的html文件,所以要new两次
      filename: 'index.html',                                //filename指定生成html文件名
      template: 'index.html',                               //template指定打包参照的模板
      chunks: ['main']                    //chunks参数指定要把哪个入口文件打包后嵌入到HTML里,可以是一个也可以是多个
    }),
    new HtmlWebpackPlugin({
      filename: 'a.html',
      template: 'a.html',
      chunks: ['a']
    })
  ]
}

运行打包命令后,我们可以看到在dist目录下,生成两个打包的JS文件和HTML文件,而打开a.html里面就内嵌了a开头的打包的js文件。而参照的template就是根目录下index.html和a.html文件。

屏幕快照 2017-08-18 上午9.51.19.png
五、使用loaders来加载资源(这一部分很重要)

webpack可以将各种各样的资源,包括CSS/SASS/LESS/PNG/JPG/JPEG等都进行打包,只是它需要应用不同的loader。

安装loaders

npm install --save-dev babel-loader babel-core babel-preset-es2015  //这是将es6转换为es5所必须的
npm install --save-dev postcss-loader css-loader style-loader autoprefixer cssnano    //安装相应loader和插件
npm install --save-dev less less-loader    //安装less和less-loader
npm install --save-dev sass sass-loader  //安装sass和sass-loader
npm install --save-dev file-loader url-loader

在使用postcss-loader的时候有点复杂,先在要目录下新建一个postcss.config.js文件,如下:

module.exports = {
  plugins: {                                //这里可以使用各种各样的插件,postcss非常强大
    'autoprefixer': {},                 //这个插件用来给CSS文件添加前缀
    'cssnano': {}                        //这个插件用来压缩CSS
  }
}

在webpack.config.js的配置文件配置loader:

var path = require('path')
var HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {             //注意这里是exports不是export
  entry: {
    main: './src/script/main.js',
    a: './src/script/a.js'
  },
  output: {
    path: path.resolve(__dirname,'dist'),
    filename: '[name]-[hash]-bundle.js'
  },
  module: {
    loaders: [                                                    //loaders在这里
      { test: /\.js$/,                                             //针对js文件里可能出现的es6语法转换
        exclude: path.resolve(__dirname, 'node_modules'),         //不检测的路径,这里用path改为了绝对路径
        include: path.resolve(__dirname, 'src'),                  //检测的路径,注意这里是绝对路径,写相对路径会报错。
        loader: 'babel-loader',
        query: {
          presets: ['es2015']                   //这个参数可以写在这里,也可以在根目录下建一个.babelrc或者写在package.json里
        } 
      },
      {
        test:/\.css$/,
        use: [                                                                   //这里写法和上面不太一样,但是效果相同
          {loader: 'style-loader' },                                     //效果依然是从右往左,先是postcss-loader
          {loader: 'css-loader', options: {importLoaders: 1}},     //这个css-loader写了一个参数,是为了让@import 进来的CSS也同样可以通过postcss-loader
          {
            loader: 'postcss-loader',
            options: {
              plugins: (loader) => [
                require('autoprefixer')({ broswers: ['last 5 versions'] }),     //这里给插件添加参数
                require('cssnano')()
              ]
            }
          }
        ]
      },
      {
      test: /\.less$/,
      loader: 'style-loader!css-loader!postcss-loader!less-loader'     //这里postcss-loader必须放在less和css之间
      },
      {
      test: /\.scss$/,
      loader: 'style-loader!css-loader!postcss-loader!sass-loader'
      },
      {
        test: /\.(jpg|png|gif|svg$)/,           //对于一些图片文件的加载,可以使用file-loader和url-loader
        use: [                                 //对于CSS中的url可以正常加载没问题,对于组件里的就需要用到require语法
          {                                     //如果是在根目录index.html那个img的话,那就没办法了,要么转换成背景图片,要么就使用import导入到入口的JS文件里,再用JS方法加上去
            // loader: 'file-loader',
            loader: 'url-loader',          //url-loader和file-loader的区别在于,可以指定一个limit参数,小于它就用base-64位编码
            options: {
              limit: 200000,
              // name: 'images/[name].[ext]',
            }
          }
        ]
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      filename: 'index.html',
      template: 'index.html',
      chunks: ['main']

    }),
    new HtmlWebpackPlugin({
      filename: 'a.html',
      template: 'a.html',
      chunks: ['a']

    })
  ]
}

对于index.html里图片url路径的问题,要么转化成背景图片,要么import到入口JS文件里再用JS的办法添加,其它没有办法。

六、最后,还有一个server和watch,不想写了,文档上写的很清楚呢

推荐阅读更多精彩内容

  • 无意中看到zhangwnag大佬分享的webpack教程感觉受益匪浅,特此分享以备自己日后查看,也希望更多的人看到...
    小小字符阅读 7,827评论 7 35
  • 写在开头 先说说为什么要写这篇文章, 最初的原因是组里的小朋友们看了webpack文档后, 表情都是这样的: (摘...
    Lefter阅读 5,038评论 4 31
  • 最近在学习 Webpack,网上大多数入门教程都是基于 Webpack 1.x 版本的,我学习 Webpack 的...
    My_Oh_My阅读 7,837评论 40 247
  • GitChat技术杂谈 前言 本文较长,为了节省你的阅读时间,在文前列写作思路如下: 什么是 webpack,它要...
    萧玄辞阅读 12,324评论 7 110
  • 早安,孩子们!今天是7月20日。今天我们跟着一只飞盘去冒险。它经历了些什么?最后选择做回飞盘,它为什么快乐? 罗强...
    银杏儿_9fbc阅读 2,249评论 0 1
  • 案例 某软件要求,从网络抓去各个城市气温信息,并依次显示:北京:15~20天津:17~22长春:12~18……如果...
    OldSix1987阅读 647评论 0 0
  • 【前言—本文内容逻辑图】 本文重点分析电商满减营销产品。 行文逻辑分为三大模块:1.基本概念;2.详细动线分析;3...
    刘景恒阅读 3,540评论 0 50
  • 儿子莫名的大爆发,躺在床上大声哭喊,不要任何人去亲近他,但也不要大家离开他的视线。感觉那时的他内在非常的矛盾,自己...
    2e03abd3e3d8阅读 48评论 0 0
  • 洛桑陀美上师:【端午祝福】 今天是端午节。端午节这一天是药师佛加持的日子。在这一天,所有的植物都被加持成药物...
    祥云_17ec阅读 271评论 0 0