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
为什么全局安装后,还需要局部安装呢?
- 在终端执行webpack命令时,使用的是全局安装的webpack
- 当在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的上级目录