使用包的版本css
webpack ->4.3.0
babel-loader ->8.0.5
npm ->6.4.1
webpack-cli ->3.3.1
复制代码
每一个章节对应一个demohtml
进入项目目录,运行 npm init来建立项目vue
npm init
复制代码
终端输入完成后会自动建立一个package.json的文件。node
{
"name": "demo1",
"version": "1.0.0",
"description": "webpack-demo",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack app.js"
},
"keywords": [
"demo"
],
"author": "cmf",
"license": "ISC",
"devDependencies": {}
}
复制代码
运行命令,引入webpack和webpack-cli,安装webpack-cli是为了在项目里面运行webpack命令。webpack
npm i webpack webpack-cli -D
复制代码
手动建立webpack.config.js。css3
touch webpack.config.js
复制代码
在终端里面经过npx运行webpack命令没法进行复杂配置。因此建立webpack.config.js是为了后面的复杂配置。 新建app.js、index.html、view文件夹、view文件夹里面建立dom.js。git
mkdir view
touch app.js
cd view
touch app.js
复制代码
代码内容详见demo1 配置 webpack.config.jses6
npx webpack
复制代码
"scripts": {
"build": "webpack"
},
复制代码
这两种方式都会自动寻找项目里面的webpack包进行打包,而且webpack会根据webpack.config.js的配置规则进行打包。github
npm i cross-env html-webpack-plugin webpack-dev-server -D
复制代码
cross-env 跨平台的解决了环境变量和参数的命令配置。
html-webpack-plugin 打包生成HTML的插件。
webpack-dev-server建立开发服务器。功能强大,接口转发、热更新等。web
新建index.html、help.js
touch index.html
touch help.js
复制代码
index.html 模板文件
<head>
<title>demo2</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
</head>
<body>
<div id="app"></div>
</body>
复制代码
help.js 封装的一些方法。
module.exports.getMode = function() {
return process.env.NODE_ENV === 'development'?'development':'production'
};
复制代码
webpack-dev-server其余配置请参考官方文档。
mode模式。默认值是production。 告知 webpack 使用相应模式的内置优化。是 webpack4新增的属性。好比mode是production,webpack会默认添加一些打包插件好比:NoEmitOnErrorsPlugin。能够节省不少配置。
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "cross-env NODE_ENV=production webpack",
"dev": "cross-env NODE_ENV=development webpack-dev-server"
},
复制代码
cross-env NODE_ENV=production 设置环境变量信息
npm run dev
复制代码
自动打开浏览器,会把app.js里面的内容自动注入到index.html里面。
代码内容详见demo3
externals防止将某些 import 的包是从外部获取依赖不是从node_modules里面获取的。
例如咱们在app.js里面
// app.js
import Vue from 'Vue';
复制代码
index.html
<head>
<title>demo4</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
</head>
复制代码
webpack.config.js
externals:{ //外部扩展
'Vue':'window.Vue'
},
复制代码
如今app.js 里面引入的Vue是从cdn里面引入的,而不是从node_modules包里面引入的。 这样作的好处:
resolve开发者能够自定义解析规则。
resolve.modules 自定义依赖包的路径。参数是array,能够是相对目录也能够是绝对目录。默认是 [path.resolve(process.cwd(),'node_modules')]。当前命令的目录下面的node_modules文件夹。
若是一个大的项目里面有不少子项目,每一个子项目不必都安装依赖包,因此能够在各个子项目里面经过配置resolve.modules指向母项目的node_modules包。
resolve.modules 自定义引入模块时能够不带扩展名。参数是array。默认['.js','.json']
extensions:['.js','.vue','.json','.css','.less'],
复制代码
代码里面
import 'view/dom'
复制代码
会自动找到dom.js
resolve.alias 自定义路径别名。参数是object。
alias:{
'@': path.resolve(__dirname, './src')
},
// __dirname 当前文件的目录地址。
复制代码
在代码里可使用@符号指向src目录。
import '@/view/dom.js';
复制代码
好处:在很深的代码层里面若是想引入顶层的某个js文件。不须要写不少'../../../'去找文件,提升开发效率。
resolve里面有不少的自定义解析规则。有时间均可以尝试一下。
代码内容详见demo4
虽然在webpack4里面提供了mode属性来分别打包开发和生产环境,各自提供不一样的插件。可是若是clean-webpack-plugin插件想在生产环境使用在开发环境不使用,就须要每次手动更改配置,这样作很不合理,容易出错。
可使用
webpack --config 配置文件
复制代码
npm i webpack-merge -D
复制代码
新建build文件夹
mkdir build
cd build
touch weboack.build.conf.js、webpack.base.conf.js、webpack.dev.conf.js config.js help.js
复制代码
help.js 储层公共方法
var path = require('path');
module.exports.getMode = function() {
return process.env.NODE_ENV === 'development'?'development':'production'
};
module.exports.resolve = function(p){
return path.resolve(process.cwd(),p);
}
复制代码
config.js 开发与生产的配置信息
module.exports = {
dev: {
mode: 'development',
publicPath: '/',
devServer: {
port: '8899',
proxy: {
'/test/shortRent': {
target: 'http:"//www.baidu.com',
changeOrigin: true,
pathRewrite: {
'^/test/shortRent': '/evcard-evrental'
}
},
},
},
},
build: {
mode: 'production',
publicPath: './',
assetsRoot: 'you-app'
}
}
复制代码
webpack.base.conf.js 开发与生产相同的webpack配置
var path = require('path');
var help = require('./help.js');
var config = require('./config.js');
var htmlWebpackPlugin = require('html-webpack-plugin');
var mode = help.getMode();
module.exports={
entry:{
app:help.resolve('./app.js')
},
output:{
},
resolve:{ // 解析
alias:{
'@': help.resolve('./src')
},
extensions:['.js','.vue','.json','.css','.less'],
modules: ["./node_modules"]
},
externals:{ //外部扩展
'Vue':'window.Vue'
},
plugins:[
new htmlWebpackPlugin({
filename:'index.html',
template:'./index.html',
inject:true,
})
],
}
复制代码
webpack.dev.conf.js 开发环境的webpack配置
var merge = require("webpack-merge");
var webpackConfigBase = require('./webpack.base.conf');
var help = require('./help.js');
var config = require('./config.js');
module.exports=merge(webpackConfigBase,{
mode: config.dev.mode,
output:{
filename:help.assetsPath('js/[name].js'),
publicPath:config.dev.publicPath
},
devServer:config.dev.devServer
})
复制代码
webpack.build.conf.js 生产环境的webpack配置
var cleanWebpackPlugin = require('clean-webpack-plugin');
var merge = require("webpack-merge");
var help = require('./help.js');
var webpackConfigBase = require('./webpack.base.conf.js');
var config = require('./config.js');
module.exports=merge(webpackConfigBase,{
mode: config.build.mode,
output:{
filename:'assets/js/[name].[hash].js',
publicPath:config.build.publicPath,
path:help.resolve(config.build.assetsRoot),
},
plugins:[
new cleanWebpackPlugin()
]
})
复制代码
"scripts": {
"build": "cross-env NODE_ENV=production webpack --config build/weboack.build.conf.js",
"dev": "cross-env NODE_ENV=development webpack-dev-server --config build/webpack.dev.conf.js"
},
复制代码
代码内容详见demo5
loader 用来解析文件转译成浏览器能够识别的文件。如.less、.vue、.jsx等这些文件浏览器是不能正常转译的,loaders的做用就是充当着'翻译'的做用。
咱们在开发的时候都使用es6的语法去编写代码,可是有些浏览器不支持es6的代码就须要将es6转译成浏览器能够读懂的es5的代码。babel-loader的做用就是'翻译'es6代码。
安装babel-loader。参照官方的安装方式,打开官网选择webpack的安装方式。
安装依赖
npm install --save-dev babel-loader @babel/core
npm install @babel/preset-env --save-dev
复制代码
babel-loader @babel/core 是核心插件
preset-env 编译方式
配置规则
module: {
rules: [
{
test: /\.js$/, // 正则匹配,全部的.js文件都使用这个规则进行编译
exclude: /node_modules/, // 排除的文件夹。这个文件夹里面的的文件不进行转译
loader: "babel-loader", // 转译的插件
options: { // 转译的规则
presets: [ //转译器配置
[
"@babel/preset-env"
]
],
plugins: [] // 转译插件配置
}
},
]
}
复制代码
plugins(转译插件)。转译插件是用来转译单一功能的插件,好比transform-es2015-arrow-functions,这个插件只负责转译es2015新增的箭头函数。
presets(转译器)。转译器是一系列转译插件的集合。好比babel-preset-es2015就包含了es2015新增语法的全部转译插件,好比包含transform-es2015-arrow-functions(es2015箭头函数转译插件)、transform-es2015-classes(es2015 class类转译插件)等。转译器分为语法转译器和补丁转译器。 详解
在app.js里面写es6的代码
const s = new Set([1, 2, 3, 4, 5, 3, 2, 16, 7, 83, 21, 2, 1]);
var w = Object.assign({}, { w: 1, e: 4 })
console.log(w);
console.log([...s]);
function pro(v) {
return new Promise((resolve) => {
if (v) {
resolve('真11')
} else {
resolve('假22')
}
})
}
pro(true).then(res=>{
console.log(res)
})
复制代码
运行命令
npm run build
复制代码
npm run dev
复制代码
Babel 默认只转换新的 JavaScript 句法(syntax),而不转换新的 API,好比 Iterator、Generator、Set、Maps、Proxy、Reflect、Symbol、Promise 等全局对象,以及一些定义在全局对象上的方法(好比 Object.assign)都不会转码。
因此还须要配置。 在babel@7.4之前使用@babel/polyfill为当前环境提供一个垫片。所谓垫片也就是垫平不一样浏览器或者不一样环境下的差别。
可是babel@7.4及之后这个垫片被废弃了。
import "core-js/stable";
import "regenerator-runtime/runtime";
复制代码
来代替@babel/polyfill。
core-js 在安装@babel/preset-env的时候已经安装好了。
npm i regenerator-runtime -D
复制代码
在app.js里面引入
import "core-js/stable";
import "regenerator-runtime/runtime";
复制代码
运行命令
npm run build
复制代码
useBuiltIns 这个配置属性能够解决这个问题。官方文档的配置实际上是babel@7.4之前的写法,这也形成了我懵逼了两天。
属性值 "usage" | "entry" | false, 默认是 false。
useBuiltIns: 'entry' 其实和import "core-js/stable"; import "regenerator-runtime/runtime";效果是同样的,表示把全部的转译代码都注入到打包的代码里面。可是仍是须要在代码里面引入这两个插件。
useBuiltIns: 'usage' 表示把代码里面须要用到的转译代码注入到打包的代码里面。就不须要引入core-js/stable了。可是regenerator-runtime/runtime仍是须要继续引入。
{
test: /\.js$/, // 正则匹配,全部的.js文件都使用这个规则进行编译
exclude: /node_modules/, // 排除的文件夹。这个文件夹里面的的文件不进行转译
loader: "babel-loader", // 转译的插件
options: { // 转译的规则
presets: [ //转译器配置
[
"@babel/preset-env", {
useBuiltIns: "usage"
}
]
],
plugins: [] // 转译插件配置
}
},
复制代码
运行打包命令
npm run build
复制代码
打包报错了
{
test: /\.js$/, // 正则匹配,全部的.js文件都使用这个规则进行编译
exclude: /node_modules/, // 排除的文件夹。这个文件夹里面的的文件不进行转译
loader: "babel-loader", // 转译的插件
options: { // 转译的规则
presets: [ //转译器配置
[
"@babel/preset-env", {
useBuiltIns: "usage",
corejs: 3
}
]
],
plugins: [] // 转译插件配置
}
},
复制代码
运行打包命令
npm run build
复制代码
打包的文件中有21个promise。
这样作的好处就是使用哪一种es语法就引入哪一种转译器,避免代码过大。为何还须要继续引入regenerator-runtime/runtime呢?由于它的代码太少了,@babel/preset-env没有像corejs同样进行配置。若是不引入async、await就不能使用了。
动态 polyfill
polyfill.io是动态polyfill解决方案最好的方法。
用最新的Chrome打开polyfill.io/v3/polyfill…
去除useBuiltIns配置
<script src="https://cdn.polyfill.io/v3/polyfill.min.js"></script>
复制代码
后面我又用vivo Y13手机, 14年的安卓4.2.2手机测试了一下。是能够用的,es七、es6均可以正常运行。
对于最新的 safari 浏览器来讲,不须要任何 polyfill,因此返回的内容为空。对于 iie7浏览器 来讲,须要 URL 对象的 polyfill,因此返回了对应的资源。
babel-loader还有不少配置不少坑,遇到就查文档或者google吧。
代码内容详见demo6
样式loader,这些都是官方提供的样式loader。
好比 使用less做为样式语法。 首先安装style-loader css-loader。
npm i style-loader css-loader -D
复制代码
less-loader文档里面显示须要安装
npm install --save-dev less-loader less
复制代码
body{
color: lawngreen;
}
.logo{
background: #f60;
height: 400px;
width: 400px;
background-repeat: no-repeat;
transition: all 1s;
display: flex;
}
.logo:hover{
height: 600px;
width: 600px;
transform: translateY(60px);
}
复制代码
在app.js 里面引入
import './src/assets/css/base.less';
复制代码
运行命令
npm run dev
复制代码
less文件里面的transition和transform都是css3的样式,若是想自动的生成带前缀的代码则须要postcss-loader,也须要postcss-loader的一个插件autoprefixer
安装依赖
npm i autoprefixer postcss-loader -D
复制代码
更改配置
{
loader: "postcss-loader",
options: {
plugins: [
require("autoprefixer")({
browsers: [
'last 10 Chrome versions',
'last 5 Firefox versions',
'Safari >= 6',
'ie> 8'
]
})
]
}
},
复制代码
npm run dev
复制代码
home.less里面的代码并无进行css3的转化。这时咱们须要配置在 css-loader 中使用 importLoaders 属性。
以前一直运行的是开发环境,咱们运行一下生产打包命令
npm run build
复制代码
打包后并无css文件。 把代码放入服务器或者使用http-server起一个本地的服务器。
这时咱们须要引入mini-css-extract-plugin进行css代码的抽离,以及打包插件optimize-css-assets-webpack-plugin在打包的时候进行css代码压缩。
npm i mini-css-extract-plugin optimize-css-assets-webpack-plugin -D
复制代码
按照官方的语法进行配置
npm run build
复制代码
css的代码已经被抽离了而且压缩了。
查看官网有关于HMR解释。
模块热替换(HMR - Hot Module Replacement)功能会在应用程序运行过程当中替换、添加或删除模块,而无需从新加载整个页面。
按照官方的实例。 首先更改devServer的配置,设置hot属性为true。
由于设置模块热加载是开发环境须要的。因此更改webpack.dev.conf.js的配置。
plugins:[
new webpack.HotModuleReplacementPlugin()
]
复制代码
因为mini-css-extract-plugin不支持HMR,因此在开发环境继续使用style-loader。 如今css的HMR已经配置好了。
{
test: /\.(png|jpg|gif)$/,
use: [{
// 须要下载file-loader和url-loader
loader: "url-loader",
options: {
limit: 5 * 1024, //小于5kb将会已base64位图片打包处理
// 图片文件输出的文件夹
outputPath: help.assetsPath("images"),
name: '[name].[ext]'
}
}]
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
outputPath: help.assetsPath("fonts")
}
},
复制代码