前提:确保已安装node,为了安装速度快一些,使用cnpm源,安装cnpm:npm i cnpm -g
注意:Mac环境下,操作全局环境,需要开启root权限,使用sudo npm i cnpm -g (sudo表示开启root权限,其他操作全局的npm或者cnpm同理,需要在命令前面加上sudo)
建立如下的目录结构,注意文件夹和文件名都和图中相同:
接下来全局安装webpack,进入项目根目录(webpack-study目录)的终端,输入命令:cnpm i webpack -g
输入命令webpack-v查看版本,发现会报如下提示:
因为webpack4开始,需要配套安装webpack-cli,输入no,因为webpack刚刚是全局安装的,所以webpack-cli也需要全局安装。
输入命令:cnpm i webpack-cli -g
安装完成后,再次输入webpack-v查看版本,如果出现下图所示版本号,则webpack4安装成功:
输入命令 cnpm init 进行项目的初始化,成功之后,根目录下会多一个package.json文件。
安装jquery包: cnpm i jquery -D (-D 表示将安装的包保存在package.json文件中的devDependencies对象中)。
注意:一定加上-D,如果中途安装包出现错误的时候,把整个node_module包删掉,然后执行cnpm i命令,它会根据package.json文件中的配置去下载那些包。
接下来在index.html文件中输入以下代码:
Document
在index.js文件中输入以下代码:
import $ from 'jquery'
$('#test').text('August')
浏览器中打开index.html文件,会发现控制台报错,因为import是ES6的语法,浏览器不能解析。
webpack4已经不能用webpack file1 file2来进行打包了,直接输入命令:webpack
webpack4会自动寻找src目录下的index.js文件,并将打包之后的文件,自动新建dist文件夹,并默认dist下的main.js文件就是打包生成的文件。
注意一定要有src目录下的index.js文件,否则会报错。
运行webpack命令之后,有这样的警告:
webpack4需要指定生产还是开发模式,再次输入命令:webpack --mode development 指定开发模式,可以发现警告已经没有了。
但是每次输入这个命令比较繁琐,可以在package.json文件中的scripts对象中新增一条配置:
现在执行命令 npm run dev 就相当于webpack --mode development,可以把这个命令执行试一下。
最后,我们将index.html引入的js文件改成刚刚生成的main.js文件之后,再用浏览器打开index.html,可以看到代码成功生效了。
所以webpack的作用之一,就是将一些高级语法转换成浏览器可以识别的语法,兼容浏览器。
在根目录下新建文件webpack.config.js文件,注意,一定是这个名字,webpack打包时会自动寻找这个配置文件。
如果不想有src目录,也不想有index.js文件,想随便自定义自己的文件,这个时候就可以修改webpack配置文件。
在这个配置文件中输入:
const path = require('path')
module.exports = {
entry: path.join(__dirname, './src/main.js'),//入口文件
output: {
path: path.join(__dirname, './dist'), //出口(打包后)文件路径
filename: 'bundle.js' //出口(打包后))文件名
}
}
entry指定的是你想要打包的入口文件,output指定的是打包后的出口文件,现在将src目录下的index.js文件重命名为main.js文件,并将dist文件夹删除,最后运行打包命令:npm run dev。
注:每次修改配置文件都需要重新运行打包命令。
如上图所示,webpack配置文件生效,最终将main.js文件打包成了bundle.js文件。
需要注意的是,index.html文件之前引入的是打包后的main.js文件,现在打包后文件我们指定为bundle.js文件,所以需要将index.html引入的js文件改为bundle.js,打开页面,能正常显示。
假设现在有个需求,需要将页面内容的August改为September,很简单,只需要将src下main.js修改一下就行,问题是,由于html引用的是打包后文件,所以需要改完需要再执行打包命令。这个时候,假设又需要改回August了,你需要再修改,再打包,每次修改一点想看页面效果,都需要重新打包,这样太繁琐。
所以webpack-dev-server就出现了,它可以实时监听我们文件的变化,自动帮我们编译打包命令。
安装webpack-dev-server:cnpm i webpack-dev-server -D
安装之后出现下图所示警告:
由于webpack-dev-server依赖webpack,但是我们webpack是安装在全局的,需要再这个项目下安装局部的webpack,执行以下命令:
cnpm i webpack -D
cnpm i webpack-cli -D
安装成功之后,打开package.json文件,scripts中dev属性修改成如下代码:
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "webpack-dev-server --mode development"
},
webpack-dev-server已经集成了webpack命令的作用,所以运行webpack-dev-server命令和webpack一样,只不过webpack-dev-server还能自动监听文件变化,自动打包。
运行命令:npm run dev
webpack-dev-server会自动启动一个本地服务器(webpack是基于node的),默认端口是8080,在浏览器输入localhost:8080,可以看到如下页面,说明安装配置成功:
这需要我们手动打开浏览器输入地址,webpack-dev-server提供了几个参数,可以执行完命令后,自动打开浏览器,package.json文件作如下修改:
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "webpack-dev-server --mode development --open 'google chrome' --port 3000"
},
如上配置意思是,默认以chrome浏览器打开,并修改默认端口为3000,保存文件后,重新运行npm run dev命令,可以发现浏览器已经自动打开了。
此外,还有几个参数:
--hot表示热加载,意思是默认每次重新编译都是生成一个新的打包文件,热加载则是你改了哪些,就局部更新打包文件的部分内容。
如果想局域网内其他主机也可以访问你的项目,需要增加配置,----host 0.0.0.0
如果想打开浏览器就能看到页面而不是这个目录结构,可以增加配置, --content-base src/
ps:除了可以在package.json文件中配置dev,还可以在webpack.config.js文件中通过devServer属性来修改配置。
然后我们修改main.js文件,改成September,然后刷新页面,发现并没有生效。
回头看下刚刚运行webpack-dev-server的命令后的提示信息:
第二行告诉我们它默认的output(生成的打包文件的输出目录)是/,也就是根目录,所以我们需要将index.html文件中的引入路径改为:
现在对main.js作任何修改都能不用执行打包命令,也不用刷新浏览器就能看到变化。
这里默认打包后的文件在根目录下,但是根目录下,我们并没有看到有这个文件,其实它是在内存中存放,既然打包后的文件在内存中存放,那是不是也可以让index.html文件也在内存中存放,并自动引入我们打包后的js文件呢?
这需要安装插件:html-webpack-plugin
安装:cnpm i html-webpack-plugin -D
安装之后,需要在webpack的配置文件webpack.config.js中作如下修改:
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
entry: path.join(__dirname, './src/main.js'),//入口文件
output: {
path: path.join(__dirname, './dist'), //出口(打包后)文件路径
filename: 'bundle.js' //出口(打包后))文件名
},
plugins: [
new HtmlWebpackPlugin({
// 指定模板页面,将来根据这个指定的路径生成内存中的页面
template: path.join(__dirname, './src/index.html'),
// 指定生成页面的名称
filename: 'index.html'
})
]
}
然后我们将index.html中引入的script文件删除,不引入任何的script文件,然后重新运行npm run dev,记得保存修改后的配置文件。
运行之后,可以看到页面会正常显示。
html-webpack-plugin会帮我们将html文件存到内存中,并自动帮我们引入打包后的文件,我们可以查看下网页源代码:
可以看到多了一个script引入文件。
接下来我们新增一个css文件,尝试改变下文字颜色,然后在main.js中引入这个css文件:
import $ from 'jquery'
import './main.css'
$('#test').text('August')
保存之后,自动打包会报错:
第三行提醒我们需要一个合适的loader,因为webpack处理不了非js文件,所以我们需要安装第三方加载器,loader的作用就是解析这类webpack不能解析的文件,css需要安装css-loader和style-loader。
cnpm i css-loader style-loader -D
安装完成之后,需要在webpack配置文件进行相应的配置,增加了module属性:
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
entry: path.join(__dirname, './src/main.js'),//入口文件
output: {
path: path.join(__dirname, './dist'), //出口(打包后)文件路径
filename: 'bundle.js' //出口(打包后))文件名
},
plugins: [
new HtmlWebpackPlugin({
// 指定模板页面,将来根据这个指定的路径生成内存中的页面
template: path.join(__dirname, './src/index.html'),
// 指定生成页面的名称
filename: 'index.html'
})
],
module: {
rules: [
{test: /\.css$/, use: ['style-loader', 'css-loader']}
]
}
}
这条rule的意思是,检测到.css结尾的文件时,使用后面的加载器。
注意:loader的加载顺序是从后往前的,先解析css,再将结果交给style,顺序不能交换,保存配置文件之后重新npm run dev,可以看到css代码已经生效。
同理,less和scss也是需要安装加载器。
less安装:cnpm i less less-loader -D (less-loader内部需要依赖less)
scss安装:cnpm i node-sass sass-loader -D (sass-loader内部需要依赖node-sass)
接着配置webpack配置文件,rules中在刚刚css那条规则后面再增加scss和sass的配置:
rules: [
{test: /\.css$/, use: ['style-loader', 'css-loader']},
{test: /\.less$/, use: ['style-loader', 'css-loader', 'less-loader']},
{test: /\.scss$/, use: ['style-loader', 'css-loader', 'sass-loader']}
]
新增一个less和scss文件,随便写一点样式,然后在main.js中import这两个文件,最后执行npm run dev,如果刚刚写的样式生效,则安装配置成功。
现在我们尝试在css文件中添加一条样式,{background: url(图片路径)}
会发现会报错,和我们第一次引入css-loader的错一样,提醒我们需要一个加载器来解析url。
安装:cnpm i url-loader -D
和之前一样,也是在配置文件中新增一条rule:
rules: [
{test: /\.css$/, use: ['style-loader', 'css-loader']},
{test: /\.less$/, use: ['style-loader', 'css-loader', 'less-loader']},
{test: /\.scss$/, use: ['style-loader', 'css-loader', 'sass-loader']},
{test: /\.(jpg|jpeg|gif|png|)$/, use: 'url-loader'},
{test: /\.(ttf|woff2|woff|eot|svg)$/, use: 'url-loader'}, // 处理字体文件
]
第二行的url-loader是为了处理fontawesome或者类似的图标库,本文不再说图标引入,可以自行参考fontawesome官网,通过cnpm安装,然后import css文件,配置不需要做其他修改。
更改配置之后,执行npm run dev可以看到图片出现在页面上。
babel是JavaScript的编译器,webpack只能解析一部分es6的语法,如果我们用了更高级的es6的语法,例如我们可以在main.js中添加以下代码:
class Person {
static info = {name: 'kun', age: 20}
}
console.log(Person.info)
这段代码是什么意思,我们先不用管,只需要知道这是ES6的语法,会发现又报错:需要一个loader。
这里以最新版今年8月份发布的babel 8 版本为例安装(由官方文档可知之前的stage已移除):
cnpm i babel-loader @babel/core -D
cnpm i @babel/plugin-transform-runtime @babel/runtime @babel/plugin-proposal-class-properties -D
cnpm i @babel/preset-env
安装完成之后,项目根目录(即webpack.config.js同一级目录)下新建一个babel配置文件:.babelrc(这是个json格式的配置文件)
{
"plugins": [
"@babel/plugin-transform-runtime",
"@babel/plugin-proposal-class-properties"
],
"presets": [
[
"@babel/preset-env",
{
"useBuiltIns": "entry"
}
]
]
}
最后,像之前一样在webpack配置文件中新增一条rule
{test: /\.js$/, use: 'babel-loader', exclude: /node_modules/}
exclude的意思是,除了node_modules下的js文件,其他js都使用babel-loader解析,原因是,node_modules下js文件太多,都打包耗费性能,并且没必要打包,打包之后最终生成的代码会出错。
cnpm i vue -D
cnpm i vue-loader vue-template-compiler -D (和之前css文件一样,vue-loader是为了解析.vue文件,此处不再演示,未安装时,报错:需要一个合适的loader,)
webpack配置文件新增一条rule:
{test: /\.vue$/, use: 'vue-loader'}
这里需要注意的是,15.x之后版本的vue-loader还需要配置插件:
const VueLoaderPlugin = require('vue-loader/lib/plugin')
再在plugins属性中增加一条:
new VueLoaderPlugin()
index.html修改文件内容如下:
Document
main.js修改文件内容如下:
import $ from 'jquery'
import './main.css'
import './main.less'
import './main.scss'
import Vue from 'vue'
var vm = new Vue({
el: '#app',
components: {
test: {template: 'August
'}
}
})
如果我们是通过script方式引入vue.js的话,此时页面上应该有h1,但是我们运行npm run dev之后,发现报错:
You are using the runtime-only build of Vue where the template compiler is not available.
在node_modules文件夹下,找到刚刚安装的vue文件夹,里面有个package.json文件,打开这个文件,找到main属性:
"main": "dist/vue.runtime.common.js"
import的文件默认是package.json文件中main属性指定的文件,可以发现它并不是我们熟悉的vue.js文件,import的是运行时版本,不是完整版,参考vue官方文档:
完整版:同时包含编译器和运行时的版本。
编译器:用来将模板字符串编译成为 JavaScript 渲染函数的代码。
运行时:用来创建 Vue 实例、渲染并处理虚拟 DOM 等的代码。基本上就是除去编译器的其它一切。
也就是说,template渲染的字符串,运行时vue都无法解析。
解决方法有两类,一是使用完整版vue,二是使用运行时vue,但是需要找其他解决方法。先看第一类:
1、可以明确指定import的文件:
import Vue from 'vue/dist/vue.js'
2、第二种依旧是import vue from ‘vue’
但是需要在webpack配置文件中增加一个属性:
resolve: {
alias: {
'vue$': 'vue/dist/vue.js'
}
}
这两种都可以解决问题,页面正常显示,但是完整版比运行时vue大,性能不如运行时vue,官方也更推荐运行时vue,因为vue-loader可以编译vue文件,所以事实上是不需要vue的编译功能的。
新增一个test.vue文件:
August
将main.js作如下修改:
import $ from 'jquery'
import './main.css'
import './main.less'
import './main.scss'
import Vue from 'vue'
import test from './test.vue'
var vm = new Vue({
el: '#app',
render: function(h) {
return h(test)
}
})
注意需要import test组件。
render函数也可以渲染组件,且template编译也是调用了render函数,运行时vue只能通过render函数来渲染组件,components不行,但是.vue文件可以使用components(因为使用了vue-loader进行解析),新增一个文件test2.vue:
kun
将test组件作如下修改:
August
至此,webpack+vue所需要配置的主要插件、加载器大概就是这些了。