开始之前先了解一下webpack的几个核心概念。
- entry: 入口起点(entry point)指示 webpack 应该使用哪个模块,来作为构建其内部依赖图的开始。
- output: output 属性告诉 webpack 在哪里输出它所创建的 bundles,以及如何命名这些文件,默认值为 ./dist。
- loader: loader 让 webpack 能够去处理那些非 JavaScript 文件(webpack 自身只理解 JavaScript)
- plugins: loader 被用于转换某些类型的模块,而插件则可以用于执行范围更广的任务
- 模式(mode): 通过选择 development 或 production 之中的一个,来设置 mode 参数,你可以启用相应模式下的 webpack 内置的优化
开始撸代码:
1、新建一个文件夹取名myWebpack,进入文件夹执行下面的代码
npm init -y
npm i webpack webpack-cli webpack-dev-server --save-dev
注意:
这里的–save-dev意思是安装在开发环境下,如果没有-dev则是安装在生产环境下,生产环境的代码是打包成静态文件的,所以只需要安装在开发环境就行
2、修改代码 package.json 中 scripts 部分:
"scripts": {
"build": "webpack"
}
这时myWebpack下的package.json如下:
{
"name": "myWebpack",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"build": "webpack"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"webpack": "^4.14.0",
"webpack-cli": "^3.0.8",
"webpack-dev-server": "^3.11.0"
}
}
此时,我们执行 npm run build, 会给出以下提示/错误:
1、error: 没有入口文件
2、warning: 建议设置 mode 选项
3、我们来做一些配置解决上面的两个问题
在文件根目录下新建webpack.config.js
(名字可以随便取),内容如下:
const path = require('path');
module.exports = (env, argv) => {
return {
mode: 'production' // production | development
}
}
再次运行npm run build
就打包成功了,但是这个时候是webpack默认的一些配置,部分浏览器还不能解析es6的语法,所以我们下面来搞点事情。
接下来要做的事:
1、转换 ES6 代码,解决浏览器兼容问题(js)
2、编译css,自动添加前缀,抽取css到独立文件
3、复制并压缩html文件 html-webpack-plugin
4、打包前清理源目录文件(dist) clean-webpack-plugin
5、静态资源处理 file-loader(图片、视频等)
6、development 模式下启动服务器并实时刷新 webpack-dev-server
7、使用 webpack 4 建立 vue 项目
用 babel 转换 ES6 代码
npm i babel-core babel-loader babel-preset-env --save-dev
在根目录新建一个babel配置文件 .babelrc:
{
"presets": [
"env"
]
}
1、webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
}
]
}
}
2、 npm scripts 中配置的方法:
"scripts": {
"start": "webpack-dev-server --mode development --open",
"build": "webpack --config=webpack.config.js --module-bind js=babel-loader --mode production"
},
使用 babel-polyfill 解决兼容性问题
我们用 babel-polyfill
解决浏览器依然不支持的一些语法,导致的兼容性问题。
npm i babel-polyfill babel-plugin-transform-runtime --save-dev
.babelrc
添加配置:
{
"presets": [
"env"
],
"plugins": [
"transform-runtime"
]
}
最后在 webpack.config.js
中将 babel-polyfill
加到你的 entry 数组中:
const path = require('path');
module.exports = {
entry: [
"babel-polyfill", // 解决浏览器对js语法的兼容性
path.join(__dirname, './src/index.js') // 入口文件
],
};
编译css,自动添加前缀,抽取css到独立文件
webpack 并不会主动将你的css代码提取到一个文件,过去我们使用 extract-text-webpack-plugin
,在webpack4中我们使用mini-css-extract-plugin
来解决这个问题。
postcss-loader 用于添加浏览器前缀,相关配置我喜欢在根目录新建 postcss.config.js 配置
npm i mini-css-extract-plugin css-loader style-loader postcss-loader sass-loader --save-dev
1、webpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = (env, argv) => {
// 这里的mode只有当package.json的scripts中设置了mode时才有值
const devMode = argv.mode !== 'production'
return {
module: {
rules: [
// ...,
{
test: /\.(sa|sc|c)ss$/, // 压缩css文件
use: [
devMode ? 'style-loader' : MiniCssExtractPlugin.loader,
{ loader: "css-loader" },
{ loader: "postcss-loader" },
{ loader: "sass-loader" }
]
},
]
},
plugins: [
// ...,
new MiniCssExtractPlugin({ // 提取css为单独的文件,若无此项css将被打包进js文件
filename: 'css/[name].[hash].css',
chunkFilename: 'css/[name].[hash].css',
}),
]
}
}
2、postcss.config.js
module.exports = {
plugins: {
autoprefixer: {}
}
}
复制并压缩html文件 html-webpack-plugin
npm i html-webpack-plugin html-loader --save-dev
webpack.config.js
const HtmlWebPackPlugin = require("html-webpack-plugin");
module.exports = {
module: {
rules: [
// ...,
{
test: /\.html$/, // 无此项将不能压缩html
use: [{
loader: "html-loader",
options: {
minimize: true
}
}]
}
]
},
plugins: [
new HtmlWebPackPlugin({ // html打包压缩插件,若无此项,html文件将不会压缩也不会进入打包目录
template: "index.html",
filename: "./index.html"
}),
]
};
打包前清理源目录文件 clean-webpack-plugin
每次打包,都会生成项目的静态资源,随着某些文件的增删,我们的 dist 目录下可能产生一些不再使用的静态资源,webpack并不会自动判断哪些是需要的资源,为了不让这些旧文件也部署到生产环境上占用空间,所以在 webpack 打包前最好能清理 dist 目录。
npm install clean-webpack-plugin --save-dev
下面是最新的写法,原来那种方式已经不行了,需要注意。
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = {
plugins: [
new CleanWebpackPlugin(), // 打包之前清理上一次打包的文件夹
]
};
静态资源处理 file-loader
npm install file-loader --save-dev
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.(png|jpg|jpeg|gif)$/, // 打包图片文件到指定目录
use: [
{
loader: 'file-loader',
options: {
context: __dirname + '/',
name: devMode ? '[path][name].[ext]' : '[hash].[ext]',
// publicPath: devMode ? 'src/assets' : '../dist/img/', // 引入图片的图片路径,比如css引入的图片路径'../images/xx.jpg'将变为‘../img/xx.jpg’
outputPath: devMode ? '' : 'img/', // 打包后存放的目录
esModule: false // 此项为webpack4新特性,不设置则引入的图片路径均变为[object module]
}
}
]
]
}
]
}
}
development 模式下配置服务器端口
plugins: [],
devServer:{
// 设置基本目录结构
contentBase:path.resolve(__dirname,'./'),
//服务器的ip地址 可以使用ip也可以使用localhost
host:'localhost',
//服务器压缩是否开启
compress:true,
//配置服务端口号
port:9999
}
使用 webpack 4 建立 vue 项目
修改目录结构如下
├── src
│ ├── assets # 静态资源
│ │ └── logo.png
│ ├── components # 组件
│ │ └── demo.vue
│ └── styles
│ │ └── index.css
│ ├── index.js # 入口文件
│ ├── app.vue # 最外层那个组件
├── .babelrc
├── index.html # html模板
├── package-lock.json
├── package.json
├── postcss.config.js
└── webpack.config.js
npm i vue --save
npm i vue-loader vue-template-compiler node-sass sass-loader --save-dev
1、webpack.config.js
const VueLoaderPlugin = require('vue-loader/lib/plugin')
module.exports = (env, argv) => {
const devMode = argv.mode !== 'production'
return {
resolve: {
extensions: ['.vue','.js','.css'], // 配置了这一项,引入的对应文件后缀自动解析,比如引入app.vue,只需要写app即可
alias: {
'vue$': 'vue/dist/vue.esm.js' //内部为正则表达式 vue结尾的
}
},
entry: [
"babel-polyfill", // 解决浏览器对js语法的兼容性
path.resolve(__dirname, './src/index.js') // 入口文件
],
output: {
path: path.resolve(__dirname, 'dist'),
filename: "js/[name].[chunkhash].js" // js文件将打包到dist/js/name.hash.js
},
module: {
rules: [
// ...
// 解析vue
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
loaders: {}
}
},
// 处理scss
{
test: /\.scss$/,
use: [
devMode ? 'style-loader' : MiniCssExtractPlugin.loader,
'css-loader',
'postcss-loader',
'sass-loader',
]
}
]
},
plugins: [
// ...
new VueLoaderPlugin()
]
}
};
2、index.js
import Vue from 'vue'
import app from './app'
new Vue({
el: '#app',
template: ' ',
components: { app }
})
一个简单的vue项目就搭建好了。