webpack学习

webpack学习

一、初识webpack

​ 我们已经知道了模块化开发是非常重要和必要的了,而且也了解了一些前端模块化的方案:AMD、CMD、CommonJS、ES6.

​ 在ES6之前,要是想使用上面那些模块化开发的方案,那就必须得依靠一些对这些方案有底层支撑的一些工具,因为ES5的语法中根本就没这些东西,我们需要有东西来对这些方案的语法进行解析。而且,在模块化开发完成之后还要进行一个整合和打包,处理模块间的依赖关系。一个项目中,有多个模块进行导出和导入,关系会变得非常复杂,所以需要有工具帮我们处理一下这些依赖关系。

webpack处理模块间依赖关系什么意思?

​ 就是你只需要将一个入口的js文件进行打包,它会自动帮你找是否有依赖其它包,一层一层的处理下去然后打包成一个浏览器认识的js文件。

a.什么是打包?

1.打包就是将各种资源模块进行打包合并成一个或者多个包(Bundle)

2.对资源进行处理,比如说压缩图片,预处理Sass,less,将ES6语法转成ES5的语法,将TypeScript转成javascript等等

b.打包的工具有很多,像是grunt/gulp,它们有什么不同?

1.grunt/gulp的核心是Task,通过配置一系列的task,定义task要处理的事务,比如说压缩图片,预处理Sass,less,将ES6语法转成ES5的语法,将TypeScript转成javascript等等,然后让grunt/gulp来依次执行这些task,让整个流程自动化,所以grunt/gulp也被称为前端自动化任务管理工具它们强调的是前端流程的自动化,模块化不是它们的核心,也是通过配置一些东西,把模块化作为一个task去处理而已,而且会很复杂。

2.webpack更加强调模块化开发的管理,官网解释webpack就是一个现代的JavaScript应用的静态模块打包工具,而压缩图片,预处理Sass,less,将ES6语法转成ES5的语法,将TypeScript转成javascript等等的功能只不过是它的附加功能。

二、安装webpack

webpack对于模块化开发很重要,所以就先安装来使用吧

webpack要想运行需要依赖Node.js环境。Node.js为了正常运行很多代码,需要依赖各种包,所以它自带了一个软件包管理工具npm。所以通过npm来安装webpack。

webpack有两种安装方式

​ 1.全局安装,version是指定的版本 ,-g表示全局安装global

npm install webpack@version -g

​ 2.局部安装

cd 想要安装的目录
npm install webpack@version --save-dev

为什么全局安装后,还需要局部安装呢?

  1. 在终端执行webpack命令时,使用的是全局安装的webpack
  2. 当在package.json中定义了scripts时,其中包含的webpack命令首先是找局部的webpack,找不到才用全局的。

三、webpack起步

现在可以进行模块化开发了

mathUtil.js

function add(num1,num2) {
  return num1 + num2;
}
function mul(num1,num2) {
  return num1 * num2;
}
//CommonJS
module.exports = {
  add,mul
};

main.js

//CommonJS
const {add,mul} = require("./mathUtil.js");
console.log("Hello webpack");
console.log(add(10, 20));
console.log(mul(10, 20));
//ES6
import * as author from "./author.js";

console.log(author.name);
console.log(author.age);
console.log(author.height);

author.js

//ES6
const name = "WaiGo";
const age = 20;
const height = 1.80;
export {
  name,age,height
}

通过在终端输入webpack指令进行打包,因为浏览器本身肯定不认识CommonJS

webpack main.js的地址 想要放入打包后的Js文件的地址

你会发现这里只是对main.js进行了打包,没有管mathUtil.js和author.js,webpack会自动找main.js中依赖了哪些模块然后去进行一些处理的,这就是处理依赖关系。

然后将打包好的js文件进行引入使用就可以了。

四、webpack.config.js配置和package.json配置

​ 1.上面的webpack指令是不是挺麻烦的,每次都要写将哪里的入口文件打包到哪个出口文件,挺麻烦的,所以下面就通过webpack.config.js的配置文件实现我们只需要写一个webpack指令,它就知道是把main.js给打包到bundle.js中。

module.exports = {
  //需要打包的文件,入口JS文件
  entry: "./src/main.js",
  //1.入口文件可以直接写当前路径的main.js文件,直接写相对路径就可以,
  // 就是相对于webpack.config.js的路径
  //2.output是出口,这需要一个对象
  //包括这个输出文件的地址path和文件名filename
  //dist是distribute发布的意思
  output: {
    path:"./dist",
    filename:"bundle.js"
  }
};

注意这个path一定要是一个绝对路径,写相对路径会报错

Invalid configuration object. Webpack has been initialised using a configuration object that does not match the API schema.

  • configuration.output.path: The provided value "./dist" is not an absolute path!

错误信息说,这是无效的配置对象,webpack在初始化的时候使用配置对象但是并没有符合API schema的限制,因为"./dist"不是一个绝对路径

const path = require("path");
module.exports = {
  //需要打包的文件,入口JS文件
  entry: "./src/main.js",
  //1.入口文件可以直接写当前路径的main.js文件,直接写相对路径就可以,
  // 就是相对于webpack.config.js的路径
  //2.output是出口,这需要一个对象
  //包括这个输出文件的地址path和文件名filename
  //dist是distribute发布的意思
  //3.path是一个绝对路径,那么肯定不要自己把它给写死了,应该是动态获取的
  //Node里有个叫做path的模块,path就能拿到当前webpack.config.js的路径
  //所以要先下载这个依赖。
  // 1.想要使用Node里面的模块,就必须先有个package.json文件,它是Node对
  //  包进行管理需要用到的文件,先通过npm init来创建这个json文件
  // 2.如果这个json文件中有一些依赖的话,需要通过npm install来下载这些依赖
  output: {
    //__dirname(注意注意:这个dirname前面是有两个下划线的)是Node上下文的一个
    // 全局变量,保存着webpack.config.js这个文件的绝对路径,path模块中有个
    // resolve方法可以进行路径拼接,就可以拼接出输出绝对路径了
    path:path.resolve(__dirname,"dist"),
    filename:"bundle.js"
  }
};

五、局部安装webpack

我们之前使用的webpack是全局的webpack,可能我们的项目使用的webpack的版本和全局的版本不一致,所以就要有个项目本地的webpack,然后把webpack指令映射到package.json中的scripts脚本中,这样在使用npm run的指令的时候使用的就是项目本地的webpack而不是全局的webpack了。

通过下面的指令安装局部webpack

cd 到需要安装的目录
npm install webpack@version --save-dev

--save-dev表示是开发时依赖

npm官方镜像安装非常慢,但是使用淘宝的cnpm就挺快的

npm install -g cnpm --registry=https://registry.npm.taobao.org

这样就可以通过cnpm来替换npm下载了

六、配置package.json文件

将webpack指令映射成npm run build指令,这样才能使用本地的webpack而不是全局的webpack。不然就得写这么一长串指令了

node_modules/.bin/webpack

就这样配置映射

"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack"//这就可以使用npm run build指令打包了
  },

七、loader

webpack能够把css,TypeScript等等的东西也当成一个模块进行处理,这样就不用引入很多文件了,不过原始的webpack指令是没办法处理js之外的文件的,所以就需要loader来扩展webpack的功能。

使用步骤:

​ 1.通过npm 安装需要使用的loader

​ 2.在webpack.config.js中的module关键字下进行配置

可以进入webpack官网中找到相应的loader进行学习用法

官网这样解释loader

loader 用于对模块的源代码进行转换。loader 可以使你在 import 或"加载"模块时预处理文件。因此,loader 类似于其他构建工具中“任务(task)”,并提供了处理前端构建步骤的强大方法。loader 可以将文件从不同的语言(如 TypeScript)转换为 JavaScript,或将内联图像转换为 data URL。loader 甚至允许你直接在 JavaScript 模块中 import CSS文件!

a.如何将css文件打包

  • style-loader 将模块的导出作为样式添加到 DOM 中
  • css-loader 解析 CSS 文件后,使用 import 加载,并且返回 CSS 代码

需要这两个loader,先安装

cnpm install style-loader --save-dev
cnpm install css-loader --save-dev

在webpack.config.js文件中进行配置

module: {
  rules: [
    {
      test: /\.css$/,
      //1.css-loader只负责css文件加载,不会解析
      //2.style-loader负责将样式添加到DOM中
      //使用多个loader时,webpack是从*右向左读*的,
      // 若是没使用css-loader解析就用style-loader会直接报错
      //所以顺序不能乱
      use: ['style-loader','css-loader' ]
    }
  ]
}

编写一个css文件并在main.js中导入

//导入css文件
require("./css/normal.css");

这时候使用npm run build就可以打包css了

若是没有css-loader和style-loader打包css会报错,说需要一些合适的loader才能打包。

b.如何打包less文件

打包less,除了上面的两个loader之外还要一个less-loader和less(用来转换less成css的工具)

同样,第一步安装

cnpm install --save-dev less-loader less

第二步,配置

{
        test: /\.less$/,
        use: [{
          loader: "style-loader" // creates style nodes from JS strings
        }, {
          loader: "css-loader" // translates CSS into CommonJS
        }, {
          loader: "less-loader" // compiles Less to CSS
        }]
      }

把这个加在modul的rules里面就可以了,然后在入口文件中依赖less文件,然后打包就可以了。

c.如何进行图片打包

​ webpack把图片也当作了模块,而且不需要像引入css文件那样使用import/require来导入,如果在css中使用了就算是引用了。然后通过url-loader或者file-loader来打包。

若是file-loader打包就会将这个图片以32位哈希值为文件名拷贝一份放在dist文件夹下。

若是使用url-loader打包就会将图片给转换成base64的字符串。

使用url-loader还是file-loader是看的modul.rules里那个url-loader配置的options里的limit的阈值,大于就使用file-loader。若是使用file-loader就会在dist中产生一个新的名字的图片。

所以需要安装两个loader,url-loader和file-loader

cd 对应目录
npm install --save-dev url-loader
npm install --save-dev file-loader

配置一下url-loader就可以进行打包了,file-loader是不需要特别配置的,当图片的大小超过url-loader的阈值后就自动使用file-loader了。

{
        test: /\.(png|jpg|gif)$/,
        use: [
          {
            loader: 'url-loader',
            options: {
              //当加载的图片小于limit时,会将图片编译成base64的字符串形式
              //当加载的图片大于limit时,就会去使用file-loader来加载
              limit: 8196//文件的大小8kb
            }
          }
        ]
      }

因为使用这个css文件的html文件没有在dist中,那么它是加载不到这个图片的,为了让html文件能够加载到这个图片,我们需要对webpack.config.js文件里的output添加一个属性publicPath:'dist/',这样它在打包所有路径的时候都会在前面先加一个这个属性的值。这样就找得到了。它原来会将图片相对于dist文件夹的路径返回放到图片的地址那里,但是由于html文件在外面肯定找不到了

output: {
  //__dirname(注意注意:这个dirname前面是有两个下划线的)是Node上下文的一个
  // 全局变量,保存着webpack.config.js这个文件的绝对路径,path模块中有个
  // resolve方法可以进行路径拼接,就可以拼接出输出绝对路径了
  path:path.resolve(__dirname,"dist"),
  filename:"bundle.js",
  publicPath:"dist/"
}
打包图片文件改名

默认使用file-loader产生的图片名是像这样子5c6dc1ca2516354142c5612a8021f9e4的一个32位的哈希值,但是开发人员可能就不知道是哪一张图片了,那就需要对这个图片进行我们想要的改名。

在url-loader的options里添加一个name属性,值为"img/[name].[hash:8].[ext]"

img/:它会在dist中产生一个img文件夹

[name]:是Node中的一个语法,拿到原来图片的名字

[hash:8]:是Node中的一个语法,取8位哈希值,他会自动运行哈希算法然后返回8位放在这里

[ext]:extension表示扩展名,这是拿到原来的扩展名

{
  test: /\.(png|jpg|gif)$/,
  use: [
    {
      loader: 'url-loader',
      options: {
        //当加载的图片小于limit时,会将图片编译成base64的字符串形式
        //当加载的图片大于limit时,就会去使用file-loader来加载
        limit: 8196,//文件的大小8kb
        name:"img/[name].[hash:8].[ext]"
      }
    }
  ]
}

d.ES6语法转成ES5的处理

第一步:安装

npm install --save-dev babel-loader@7 babel-core babel-preset-es2015

第二步:配置

{
  test: /\.js$/,
  exclude: /(node_modules|bower_components)/,
  use: {
    loader: 'babel-loader',
    options: {
      presets: ['es2015']
    }
  }
}

exclude表示这些文件不进行压缩

官网那种方式需要配置一个babel.rc文件,还没学到就没用了,就先用老师这种方式吧。

八、引入Vue.js

在webpack中,vue也是作为一个模块来看待的,所以是import Vue from "vue";这样子来使用的,现在需要先把Vue给下载到项目本地。由于Vue不只是开发时需要依赖,在运行时也是需要依赖的所以要指定为--save

nam install vue --save

使用

<div id="app">
  {{message}}
</div>
<script src="dist/bundle.js"></script>
import Vue from "vue";
new Vue({
  el:"#app",
  data:{
    message:"Hello Webpack~~~"
  }
});

webpack中的Vue默认使用的是runtime-only的版本,这个是无法解析template的,需要runtime-complier版本,所以就报了下面这个错误。这里老师没仔细说这两个版本的区别,到后面再补充。这里修改一下webpack的配置就可以使用了。

bundle.js:1346 [Vue warn]: You are using the runtime-only build of Vue where the template compiler is not available. Either pre-compile the templates into render functions, or use the compiler-included build.

//在module.exports = {}中定义一个resolve
resolve:{
  //别名
  alias:{
    //在import的时候会去这个文件夹中找
    'vue$':"vue/dist/vue.esm.js"
  }
}

九、el和template的区别

在之前学习Vue的过程中我们写的代码都是直接对vue实例对象挂载的那个div进行操作,都是在以后的开发中,我们是不希望手动的频繁去修改html文件中的东西的。就是让<div id="app"></div>这个挂载到vue实例对象中的DOM元素就这样为空,但是我们又需要在在里面显示东西,那应该怎么处理呢?

这就提到template属性了,在vue实例中若是既定义了el属性,也定义了template属性,那么在运行的时候template中的元素会将el挂载的那个元素完全给替换掉的。

new Vue({
  el:"#app",
  template:`
  <div>
    <h2>{{message}}</h2>
    <button @click="btnClick">按钮</button>
  </div>
  `,
  data:{
    message:"Hello Webpack~~~"
  },
  methods:{
    btnClick() {
      console.log("按钮点击了");
    }
  }
});

第一步升级:将template给抽离成一个组件,不然Vue实例中的代码太多了

import Vue from "vue";
const app = {
  template:`
  <div>
    <h2>{{message}}</h2>
    <button @click="btnClick">按钮</button>
  </div>
  `,
  data(){
    return {
      message:"Hello Webpack~~~"
    }
  },
  methods:{
    btnClick() {
      console.log("按钮点击了");
    }
  }
};
new Vue({
  el:"#app",
  template:`<app/>`,
  components:{
    app
  }
});

第二步升级:把组件对象抽离到一个咱们放这个组件对象的文件中,这样就好管理了

export default {
  template:`
  <div>
    <h2>{{message}}</h2>
    <button @click="btnClick">按钮</button>
  </div>
  `,
  data(){
    return {
      message:"Hello Webpack~~~"
    }
  },
  methods:{
    btnClick() {
      console.log("按钮点击了");
    }
  }
}

这样子使用

import Vue from "vue";
import App from "./vue/app.js";
new Vue({
  el:"#app",
  template:`<App/>`,
  components:{
    App
  }
});

第三步升级:将template,js代码分离

创建一个Vue Component文件,就是.vue文件

<!--模板-->
<template>
  <div>
    <h2 class = "title">{{message}}</h2>
    <button @click="btnClick">按钮</button>
  </div>
</template>
<!--JS-->
<script>
  export default {
    name: "app",
    data(){
      return {
        message:"Hello Webpack~~~"
      }
    },
    methods:{
      btnClick() {
        console.log("按钮点击了");
      }
    }
  }
</script>
<!--样式-->
<style scoped>
  .title{
    color:lightgreen;
  }
</style>

使用一个单独的组件文件,代码看起来是真的清爽啊。可是这样子是打包不了的,因为webpack原先不能处理.vue文件,所以要下载相应的loader

cnpm install --save-dev vue-loader vue-template-compiler

webpack.config.js配置

{
        test: /\.vue$/,
        use:['vue-loader']
      }

这个指令会安装最新的vue-loader,但是自从vue-loader14点几的版本之后要想使用这个vue-loader还需要配置一个插件。不然就会报错

Module build failed: Error: Cannot find module '@vue/component-compiler-utils'

若是不想要配置那个插件就得安装一个小于14的版本,修改packege.json中的版本号后重新安装。

"vue-loader": "^13.0.0",

然后重新安装

cnpm install

现在就可以正常打包运行了。这里说一下,定义组件文件名的时候首字母最好大写

父子组件例子

子组件

<template>
  <div>
    <h2>我是标题</h2>
    <p>我是共产主义接班人</p>
    <h2>{{message}}</h2>
  </div>
</template>

<script>
  export default {
    name: "Cpn",
    data(){
      return {
        message : "马克思主义万岁"
      }
    }
  }
</script>

<style scoped>

</style>

父组件

<!--模板-->
<template>
  <div>
    <h2 class = "title">{{message}}</h2>
    <button @click="btnClick">按钮</button>
    <Cpn></Cpn>
  </div>
</template>
<!--JS-->
<script>
  import Cpn from "./Cpn.vue";
  export default {
    name: "app",
    data(){
      return {
        message:"Hello Webpack~~~"
      }
    },
    methods:{
      btnClick() {
        console.log("按钮点击了");
      }
    },
    components:{
      Cpn
    }
  }
</script>
<!--样式-->
<style scoped>
  .title{
    color:lightgreen;
  }
</style>

十、webpack中引用文件的扩展名的问题

如果觉得后缀名麻烦不想写,可以在webpack.config.js中的resolve中配置一下extensions:[省略扩展名的文件类型]

resolve:{
  //别名
  alias:{
    //在import的时候会去这个文件夹中找
    'vue$':"vue/dist/vue.esm.js"
  },
  //后缀名
  extensions:['.js','.less','.css','.vue']
}

不过有些时候是不能省略的,比如说在你指定的路径,有个app.js和一个app.vue,那你写个app,它不知道应该是哪一个。

 import Cpn from "./Cpn";

现在省略掉后缀名就不会报错了

十一、插件plugin

插件时用于对某个现有的架构进行扩展的东西,webpack的插件就是用于对webpack本身的功能进行扩展。

plugin的使用和loader差不多,就是通过npm安装后在webpack.config.js中进行一定的配置后就可以使用了。

  • 添加版权的Plugin

    在webpack.config.js中配置

    const webpack = require("webpack");
    module.exports = {
        ...
        plugins:[
          new webpack.BannerPlugin('最终版权归XXX所有')
          ]
    }
    
  • 打包HTML的plugin

    项目最终发布的时候只是发布dist中的内容,我们之前的打包都没有把index.html文件给打包到dist文件夹中,这样dist中的html文件就没有意义了。所以需要将index.html文件给打包到dist文件夹中,这时需要使用HtmlWebpackPlugin 插件

    功能:

    • 自动生成一个index.html文件,可以指定模板来生成
    • 将打包的js文件,自动添加到生成的这html文件的body中。

    安装:

    cnpm install html-webpack-plugin --save-dev

  • js压缩的plugin

    在项目发布之前,肯定需要对js等文件进行压缩处理,就是去掉空格啊,使用简单的变量名替换原来的变量名这样,就可以将文件的体积缩小。

    第一步:安装plugin

    cnpm install uglifyjs-webpack-plugin@1.1.1 --save-dev

    就是丑化js文件

    这里指定版本1.1.1是为了符合webpack3.6.0,不然会报错,但是现在好像下载不了这个版本了,最新的版本2点几的又不能适配webpack3.6.0,所以我就先下载了最新的

    cnpm install uglifyjs-webpack-plugin --save-dev

    然后修改package.json中的版本号为1.1.1然后cpnm install去下载1点几的版本,然后就可以适配了,应该1.1.1不是一个稳定的版本,老师下载的这个版本把横幅插件的话给删除了,但是这个版本没有输出,还是打印了一行最终补全归xxx所有,以后要是出现说版本不匹配的就可以降一下版本试试。

    第二步:配置webpack.config.js

const uglifyJsPlugin = require("uglifyjs-webpack-plugin");
module.exports = {
...
plugins:[
new uglifyJsPlugin()
]
}


## 十二、搭建本地服务器

在前面的学习中,你肯定会发现,每次对main.js或者是什么进行了修改后想要验证一下,都需要npm run build进行再次打包,然后才能验证代码是否准确。这大大降低了开发效率,因为每次打包都是要把新的东西写入硬盘的。所以,搭建一个本地开发服务器就非常重要了,webpack提供了一个可选的服务器。它能时时监听我们打包文件的代码是否改变,若是改变了它会自动编译改变后的代码,然后放在内存中而不是直接写入磁盘,因为内存读写速度比磁盘快非常多。

**安装**:

> npm install --save-dev webpack-dev-server@2.9.1

这个服务器的版本和webpack的版本也有一定的对应关系,因为现在我的webpack是3.6.0,就要下载2.9.1

**配置:webpack.config.js**

```javascript
module.exports = {
  ...
  devServer:{
  contentBase:"./dist",
  inline:true//是否实时刷新
}
}

启动本地开发服务器的指令是

webpack-dev-server

但是在终端的话要在全局中定位到项目中webpack的地方才能使用这个指令,代码会是一大串。所以把这个指令映射到package.json中,就会自动去项目本地找了,而且只需要敲一段这种指令npm run dev

"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack",
    "dev" : "webpack-dev-server"
  },

使用npm run dev就能把本地开发服务器跑起来了,默认跑在8080端口。然后你可以对main.js中的东西进行一些修改,你会发现浏览器会自动刷新你修改的内容。但是这时候当服务器跑起来之后,你是需要手动去点击连接才能打开浏览器的,你可能想要它自动打开浏览器,那就在dev指令后面加一个 --open

"dev" : "webpack-dev-server --open"

十三、webpack.config.js配置文件分离

我们之前只有一个webpack.config.js配置文件,但是在开发阶段我们可能不想要进行一些打包操作,比如说Js代码的丑化,这会使得我们代码难以调试。所以现在就把原来的配置文件分成三份,一份是基本配置,一份是开发时配置,一份是发布时配置,这样在不同时间将不同的两份配置合并成一份配置文件就可以了。开发时就使用开发时配置合并基本配置。

基本配置base.config.js

const path = require("path");
const webpack = require("webpack");
const htmlWebpackPlugin = require("html-webpack-plugin");
const uglifyJsPlugin = require("uglifyjs-webpack-plugin");
module.exports = {
  //需要打包的文件,入口JS文件
  entry: "./src/main.js",
  //1.入口文件可以直接写当前路径的main.js文件,直接写相对路径就可以,
  // 就是相对于webpack.config.js的路径
  //2.output是出口,这需要一个对象
  //包括这个输出文件的地址path和文件名filename
  //dist是distribute发布的意思
  //3.path是一个绝对路径,那么肯定不要自己把它给写死了,应该是动态获取的
  //Node里有个叫做path的模块,path就能拿到当前webpack.config.js的路径
  //所以要先下载这个依赖。
  // 1.想要使用Node里面的模块,就必须先有个package.json文件,它是Node对
  //  包进行管理需要用到的文件,先通过npm init来创建这个json文件
  // 2.如果这个json文件中有一些依赖的话,需要通过npm install来下载这些依赖
  output: {
    //__dirname(注意注意:这个dirname前面是有两个下划线的)是Node上下文的一个
    // 全局变量,保存着webpack.config.js这个文件的绝对路径,path模块中有个
    // resolve方法可以进行路径拼接,就可以拼接出输出绝对路径了
    path:path.resolve(__dirname,"dist"),
    filename:"bundle.js",
    // publicPath:"dist/"
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        //1.css-loader只负责css文件加载,不会解析
        //2.style-loader负责将样式添加到DOM中
        //使用多个loader时,webpack是从右向左读的,
        // 若是没使用css-loader解析就用style-loader会直接报错
        //所以顺序不能乱
        use: ['style-loader','css-loader']
      },
      {
        test: /\.less$/,
        use: [{
          loader: "style-loader" // creates style nodes from JS strings
        }, {
          loader: "css-loader" // translates CSS into CommonJS
        }, {
          loader: "less-loader" // compiles Less to CSS
        }]
      },
      {
        test: /\.(png|jpg|gif)$/,
        use: [
          {
            loader: 'url-loader',
            options: {
              //当加载的图片小于limit时,会将图片编译成base64的字符串形式
              //当加载的图片大于limit时,就会去使用file-loader来加载
              limit: 8196,//文件的大小8kb
              name:"img/[name].[hash:8].[ext]"
            }
          }
        ]
      },
      {
        test: /\.js$/,
        exclude: /(node_modules|bower_components)/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['es2015']
          }
        }
      },
      {
        test: /\.vue$/,
        use:['vue-loader']
      }
    ]
  },
  resolve:{
    //别名
    alias:{
      //在import的时候会去这个文件夹中找
      'vue$':"vue/dist/vue.esm.js"
    },
    //后缀名
    extensions:['.js','.less','.css','.vue']
  },
  plugins:[
      new webpack.BannerPlugin('最终版权归XXX所有'),
      new htmlWebpackPlugin({
        template:'index.html'
      })
  ],
};

开发时配置,因为只有开发时需要webpack-dev-server

module.exports = {
  devServer:{
    contentBase:"./dist",
    inline:true
  }
};

发布时依赖,只有发布时才需要Js丑化

const uglifyJsPlugin = require("uglifyjs-webpack-plugin");
module.exports = {
  plugins:[
      new uglifyJsPlugin()
  ],
};

为了合并配置文件,还需要一个工具,webpack-merge

安装:

cnpm install webpack-merge --save-dev

然后使用webpack-merge进行配置文件的合并

const uglifyJsPlugin = require("uglifyjs-webpack-plugin");
const WebpackMerge = require("webpack-merge");
const baseConfig = require("./base.config");

module.exports = WebpackMerge(baseConfig,{
  plugins:[
      new uglifyJsPlugin()
  ],
});
const WebpackMerge = require("webpack-merge");
const baseConfig = require("./base.config");

module.exports = WebpackMerge(baseConfig,{
  devServer:{
    contentBase:"./dist",
    inline:true
  }
});

好的,现在webpack.config.js可以退役了

const path = require("path");
const webpack = require("webpack");
const htmlWebpackPlugin = require("html-webpack-plugin");
const uglifyJsPlugin = require("uglifyjs-webpack-plugin");
module.exports = {
  //需要打包的文件,入口JS文件
  entry: "./src/main.js",
  //1.入口文件可以直接写当前路径的main.js文件,直接写相对路径就可以,
  // 就是相对于webpack.config.js的路径
  //2.output是出口,这需要一个对象
  //包括这个输出文件的地址path和文件名filename
  //dist是distribute发布的意思
  //3.path是一个绝对路径,那么肯定不要自己把它给写死了,应该是动态获取的
  //Node里有个叫做path的模块,path就能拿到当前webpack.config.js的路径
  //所以要先下载这个依赖。
  // 1.想要使用Node里面的模块,就必须先有个package.json文件,它是Node对
  //  包进行管理需要用到的文件,先通过npm init来创建这个json文件
  // 2.如果这个json文件中有一些依赖的话,需要通过npm install来下载这些依赖
  output: {
    //__dirname(注意注意:这个dirname前面是有两个下划线的)是Node上下文的一个
    // 全局变量,保存着webpack.config.js这个文件的绝对路径,path模块中有个
    // resolve方法可以进行路径拼接,就可以拼接出输出绝对路径了
    path:path.resolve(__dirname,"dist"),
    filename:"bundle.js",
    // publicPath:"dist/"
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        //1.css-loader只负责css文件加载,不会解析
        //2.style-loader负责将样式添加到DOM中
        //使用多个loader时,webpack是从右向左读的,
        // 若是没使用css-loader解析就用style-loader会直接报错
        //所以顺序不能乱
        use: ['style-loader','css-loader']
      },
      {
        test: /\.less$/,
        use: [{
          loader: "style-loader" // creates style nodes from JS strings
        }, {
          loader: "css-loader" // translates CSS into CommonJS
        }, {
          loader: "less-loader" // compiles Less to CSS
        }]
      },
      {
        test: /\.(png|jpg|gif)$/,
        use: [
          {
            loader: 'url-loader',
            options: {
              //当加载的图片小于limit时,会将图片编译成base64的字符串形式
              //当加载的图片大于limit时,就会去使用file-loader来加载
              limit: 8196,//文件的大小8kb
              name:"img/[name].[hash:8].[ext]"
            }
          }
        ]
      },
      {
        test: /\.js$/,
        exclude: /(node_modules|bower_components)/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['es2015']
          }
        }
      },
      {
        test: /\.vue$/,
        use:['vue-loader']
      }
    ]
  },
  resolve:{
    //别名
    alias:{
      //在import的时候会去这个文件夹中找
      'vue$':"vue/dist/vue.esm.js"
    },
    //后缀名
    extensions:['.js','.less','.css','.vue']
  },
  plugins:[
      new webpack.BannerPlugin('最终版权归XXX所有'),
      new htmlWebpackPlugin({
        template:'index.html'
      }),
      new uglifyJsPlugin()
  ],
  devServer:{
    contentBase:"./dist",
    inline:true
  }
};

不过现在直接打包的话会报错的,因为webpack默认的配置文件名为webpack.config.js,你把它删除了,自然就报错了,所以现在需要在package.json中配置一下webpack的配置文件的名字

"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack --config ./build/prod.config.js",
    "dev": "webpack-dev-server --open --config ./build/dev.config.js"
  },

现在就可以打包了,不过还有个地方需要改

path:path.resolve(__dirname,"dist"),

--dirname表示配置文件当前的路径,现在变成build文件夹,所以"dist"要改成"../dist",表示到打包到build的上级目录

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 201,681评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,710评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,623评论 0 334
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,202评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,232评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,368评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,795评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,461评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,647评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,476评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,525评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,226评论 3 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,785评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,857评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,090评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,647评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,215评论 2 341