Webpack
在 webpack 的配置中 loader 有两个目标:
test
属性,用于标识出应该被对应的 loader 进行转换的某个或某些文件。use
属性,表示进行转换时,应该使用哪个 loader。
module: {
rules: [
{
test: /\.css$/,
use: [
/* 使用多个loader时,从右向左读取 */
{loader: "style-loader"},
{loader: "css-loader"}
]
}
]
}
“嘿,webpack 编译器,当你碰到「在
require()
/import
语句中被解析为 '.css' 的路径」时,在你对它打包之前,先使用css-loader
转换一下。”
1、图片文件的处理
安装开发时依赖
npm install --save-dev url-loader
当图片大小小于limit限制时,会将图片编译为base64的字符串形式。
当图片大小大于limit限制时,npm run build,会报错。没有找到file-loader。
安装开发时依赖
npm install --save-dev file-loader
代码:
body {
/*background-color: greenyellow;*/
background: url("../img/wallhaven-r2ewxq.jpg");
}
/* 配置入口和出口CommonJS语法 */
const path = require("path")
module.exports = {
entry: './src/main.js',
/* output是一个对象,path属性(动态绑定,调用path模块,npm init)和filename属性 */
output: {
path: path.resolve(__dirname, 'dist'), /* resolve用于拼接路径 */
filename: 'my-webpack-bundle.js',
publicPath: './dist/'
},
/* 配置css-loader */
module: {
rules: [
/* css文件 */
{
test: /\.css$/,
use: [
/* 使用多个loader时,从右向左读取 */
{loader: "style-loader"},
{loader: "css-loader"}
]
},
/* 图片文件 */
{
test: /\.(png|jpg|gif)$/,
use: [
{
loader: 'url-loader',
options: {
/*limit: 8192*/
/* 当加载的图片大小小于limit时,会将图片编译成base64的字符串形式 */
/*limit: 800000*/
/* 当加载的图片大小大于limit时,npm run build会报错,如果大于需要使用file-loader */
/*
ERROR in ./src/img/wallhaven-r2ewxq.jpg
Module build failed: Error: Cannot find module 'file-loader'
*/
limit: 700000,
/* 打包到dist文件夹,在output下增加publicPath属性 */
/* 给生成的图片设置名称,ext使用图片以前的扩展名 */
name: 'img/[name].[hash:8].[ext]'
},
}
]
}
]
}
}
{
"name": "imgfile",
"version": "1.0.0",
"description": "",
"main": "webpack.config.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack"
},
"author": "lwj",
"license": "ISC",
"devDependencies": {
"css-loader": "^3.5.3",
"file-loader": "^6.0.0",
"style-loader": "^1.2.0",
"url-loader": "^4.1.0",
"webpack": "^3.6.0"
}
}
2、ES6转ES5的babel
前面的代码中,使用Webpack生成的bundle.js文件中存在ES6的代码。
如果希望将ES6的语法转为ES5,更好的在浏览器运行,那么就需要使用babel。
在Webpack中,我们直接使用babel对应的loader。
npm install --save-dev babel-loader@7 babel-core babel-preset-es2015
const path = require("path")
module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'my-webpack-bundle.js',
publicPath: './dist/'
},
module: {
rules: [
/* es6转es5 */
{
test: /\.js$/,
/* 排除 */
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['es2015']
}
}
}
]
}
}
这样,即使客户使用的是较低版本的浏览器,也是支持的。
3、使用Vue的配置过程
现在我们希望在项目中使用Vuejs,那么必须需要对其有依赖,所以需要先进行安装。
注意:
因为我们在后续实际项目中也是需要Vue的,所以安装时并不是开发时依赖。
npm install vue --save
刚开始学习Vue,都是通过script标签引入源码的方式,它不是通过模块化的方式管理Vue的,既然Webpack支持模块化,那么可以将Vue作为模块安装。
安装Vue的三种方式:
- 直接下载,通过script标签引入;
- CDN引入;
- npm安装。
1、runtime-only
代码中不可以有任何的template,
2、runtime-compiler
代码中可以有template。
webpack.config.js
const path = require("path")
module.exports = {
resolve: {
alias: {
'vue$': 'vue/dist/vue.esm.js'
}
}
}
main.js
/* 安装vue模块npm install vue --save */
import Vue from 'vue'
const app = new Vue({
el: '#app',
data: {
message: 'Hello Webpack'
},
methods: {
}
});
index.html
<body>
<div id="app">
<span>{{message}}</span>
</div>
<script src="./dist/my-webpack-bundle.js"></script>
</body>
4、使用Vue的终极方案
SPA(Single Page Application)单页面应用:只有一个html页面(固定的)。
如果是多页面,通过路由vue-router。
由于.vue是特殊的文件格式,和css、图片格式一样,都需要loader。
npm install vue-loader vue-template-compiler --save-dev
Vue Loader的配置与其他加载器有些不同。除了适用vue-loader
于所有带有扩展名的文件的规则外,请.vue
确保将Vue Loader的插件添加到您的webpack配置中:
// webpack.config.js
const VueLoaderPlugin = require('vue-loader/lib/plugin')
module.exports = {
module: {
rules: [
// ... other rules
{
test: /\.vue$/,
loader: 'vue-loader'
}
]
},
plugins: [
// make sure to include the plugin!
new VueLoaderPlugin()
]
}
全部代码:
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
</div>
<script src="./dist/my-webpack-bundle.js"></script>
</body>
</html>
package.json
{
"name": "imgfile",
"version": "1.0.0",
"description": "",
"main": "webpack.config.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack"
},
"author": "lwj",
"license": "ISC",
"devDependencies": {
"babel-core": "^6.26.3",
"babel-loader": "^7.1.5",
"babel-preset-es2015": "^6.24.1",
"css-loader": "^3.5.3",
"file-loader": "^6.0.0",
"style-loader": "^1.2.0",
"url-loader": "^4.1.0",
"vue-loader": "^15.9.1",
"vue-template-compiler": "^2.6.11",
"webpack": "^3.6.0"
},
"dependencies": {
"vue": "^2.6.11"
}
}
main.js
let {sum, mul} = require('./js/mathutils');
console.log(sum(12, 13));
console.log(mul(12, 12));
require('./css/normal');
/* 安装vue模块npm install vue --save */
import Vue from 'vue'
import App from './vue/App'
new Vue({
el: '#app',
template: '<App></App>',
components: {
/* ES6:如果对象名和值一样,可以写一个 */
App,
}
});
App.vue
<template>
<div>
<span class="title">{{message}}</span>
<button v-on:click="btnClick">按钮</button>
<span>{{name}}</span>
</div>
</template>
<script>
export default {
name: "App",
data() {
return {
message: 'Hello Webpack',
name: 'ShawnYue'
}
},
methods: {
btnClick() {
console.log('btnClick');
}
}
}
</script>
<style scoped>
.title {
color: yellowgreen;
}
</style>
webpack.config.js
/* 配置入口和出口CommonJS语法 */
const VueLoaderPlugin = require("vue-loader/lib/plugin")
const path = require("path")
module.exports = {
entry: './src/main.js',
/* output是一个对象,path属性(动态绑定,调用path模块,npm init)和filename属性 */
output: {
path: path.resolve(__dirname, 'dist'), /* resolve用于拼接路径 */
filename: 'my-webpack-bundle.js',
publicPath: './dist/'
},
module: {
rules: [
/* css文件 */
{
test: /\.css$/,
use: [
/* 使用多个loader时,从右向左读取 */
{loader: "style-loader"},
{loader: "css-loader"}
]
},
/* 图片文件 */
{
test: /\.(png|jpg|gif)$/,
use: [
{
loader: 'url-loader',
options: {
/*limit: 8192*/
/* 当加载的图片大小小于limit时,会将图片编译成base64的字符串形式 */
/*limit: 800000*/
/* 当加载的图片大小大于limit时,npm run build会报错,如果大于需要使用file-loader */
/*
ERROR in ./src/img/wallhaven-r2ewxq.jpg
Module build failed: Error: Cannot find module 'file-loader'
*/
limit: 700000,
/* 打包到dist文件夹,在output下增加publicPath属性 */
/* 给生成的图片设置名称,ext使用图片以前的扩展名 */
name: 'img/[name].[hash:8].[ext]'
},
}
]
},
/* es6转es5 */
{
test: /\.js$/,
/* 排除 */
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['es2015']
}
}
},
/* vue文件 */
{
test: /\.vue$/,
use: [
{loader: 'vue-loader'}
]
}
]
},
plugins: [
new VueLoaderPlugin(),
],
resolve: {
/* 在import/require时可以省略后缀名 */
extensions: ['.js', '.vue', '.css'],
alias: {
'vue$': 'vue/dist/vue.esm.js'
}
}
}
5、横幅plugin
Webpack中的插件就是对Webpack现有功能的各种扩展,比如打包优化,文件压缩等。
loader和plugin的区别:
- loader主要用于转换某些类型的模块,它是一个转换器;
- plugin是插件,它是对webpack本身的扩展,是一个扩展器。
plugin的使用过程:
- 通过npm安装需要使用的插件,(某些webpack已经内置的插件不需要安装);
- 在webpack.config.js的plugins中配置插件。
添加版权的Plugin
该插件名称为BannerPlugin,属于webpack自带的插件。
const VueLoaderPlugin = require("vue-loader/lib/plugin")
const path = require("path")
const webpack = require("webpack")
module.exports = {
plugins: [
new VueLoaderPlugin(),
new webpack.BannerPlugin('最终版权归lwj所有.'),
]
}
重新打包,查看bundle.js文件。
6、HtmlWebpackPlugin
目前我们的index.html文件是存放在项目的根目录下的。
- 我们知道在真实发布项目时,发布的是dist文件夹下的内容,所以我们需要将index.html文件打包到dist文件夹中,这个时候就可以使用HtmlWebpackPlugin插件;
HtmlWebpackPlugin可以为我们做:
- 自动生成一个index.html;
- 将打包的js文件,自动通过script标签插入到body中。
安装插件:
npm install html-webpack-plugin --save-dev
"html-webpack-plugin": "^3.2.0",
现在不需要publicpath属性去dist目录下了,所以注释。
项目目录下的index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
</div>
</body>
</html>
main.js
import Vue from 'vue'
import App from './vue/App'
require("./css/normal")
new Vue({
el: '#app',
template: '<App></App>',
components: {
/* ES6:如果对象名和值一样,可以写一个 */
App,
}
});
App.vue
<template>
<div>
<span class="title">{{message}}</span>
<button v-on:click="btnClick">按钮</button>
<span>{{name}}</span>
</div>
</template>
<script>
export default {
name: "App",
data() {
return {
message: 'Hello Webpack',
name: 'ShawnYue'
}
},
methods: {
btnClick() {
console.log('btnClick');
}
}
}
</script>
<style scoped>
.title {
color: yellowgreen;
}
</style>
webpack.config.js
const VueLoaderPlugin = require("vue-loader/lib/plugin")
const path = require("path")
const webpack = require("webpack")
const HtmlWebpackPlugin = require("html-webpack-plugin")
module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'my-webpack-bundle.js',
},
module: {
rules: [
{
test: /\.css$/,
use: [
{loader: "style-loader"},
{loader: "css-loader"}
]
},
{
test: /\.(png|jpg|gif)$/,
use: [
{
loader: 'url-loader',
options: {
limit: 700000,
name: 'img/[name].[hash:8].[ext]'
},
}
]
},
/* es6转es5 */
{
test: /\.js$/,
/* 排除 */
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['es2015']
}
}
},
/* vue文件 */
{
test: /\.vue$/,
use: [
{loader: 'vue-loader'}
]
}
]
},
plugins: [
new VueLoaderPlugin(),
new webpack.BannerPlugin('最终版权归lwj所有.'),
new HtmlWebpackPlugin({
/* 根据此模板生成dist文件夹下的index.html,然后自动导入打包后的js文件 */
template: 'index.html',
})
],
resolve: {
extensions: ['.js', '.vue', '.css'],
alias: {
'vue$': 'vue/dist/vue.esm.js'
}
}
}
重新打包发布,自动生成的index.html。
7、对JS文件进行压缩
在项目发布之前,我们必然需要对js等文件进行压缩处理。
- 这里我们对打包的js文件进行压缩
- 我们使用第三方插件uglifyjs-webpack-plugin,并且指定版本号1.1.1,和CLI2保持一致。
npm install [email protected] --save-dev
plugins: [
new VueLoaderPlugin(),
new webpack.BannerPlugin('最终版权归lwj所有.'),
new HtmlWebpackPlugin({
/* 根据此模板生成dist文件夹下的index.html,然后自动导入打包后的js文件 */
template: 'index.html',
}),
new uglifyjsWebpackPlugin(),
],
重新打包。
bundle.js从原来的360KB压缩到130KB。
8、webpack-dev-server搭建本地服务器
在webpack中使用之前需要先安装它
npm install --save-dev [email protected]
配置
devServer: {
contentBase: './dist',
inline: true
}
不再通过npm run build,而是
或者
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack",
"dev": "webpack-dev-server"
},
通过配置脚本,执行npm run dev
,首先在本地下面找。
通过npm run dev
命令后的链接
,点击链接,可以在本地修改代码,浏览器自动刷新,显示结果。
最终,npm run build
打包。
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack",
"dev": "webpack-dev-server --open"
},
--open
:自动打开浏览器。
9、配置文件分离
开发时配置 和 编译打包时的配置