最近在研究使用webpack的使用,在查阅了数篇文章后,学习了webpack的基础打包流程.css
原本就能够一删了之了,可是以为未免有点惋惜,因此就有了这篇文章,供你们参考.html
webpack打包的教程具备时效性,有很多做者在一直维护一篇文章.超过必定时间参考价值就会降低,但愿各位了解这一点.vue
"devDependencies": { "clean-webpack-plugin": "^0.1.19", "css-loader": "^1.0.0", "html-webpack-plugin": "^3.2.0", "mini-css-extract-plugin": "^0.4.3", "vue-loader": "^15.4.2", "vue-style-loader": "^4.1.2", "vue-template-compiler": "^2.5.17", "webpack": "^4.19.1", "webpack-cli": "^3.1.0", "webpack-merge": "^4.1.4" }, "dependencies": { "vue": "^2.5.17" }
都是目前最新的稳定版本.node
咱们建立一个新的目录(learnwebpack).在下面建立src文件夹和一个index.html.webpack
而后咱们使用npm init
命令初始化一个package.json
文件,直接一路回车过去就行了.git
目录结构:github
learnwebpackweb
src保存咱们未经编译的源码.npm
index.html内容以下:json
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Webpack4 && Vue</title> </head> <body> <div id="root"> </div> <script src="./dist/app.bundle.js"></script> </body> </html>
在webpack4中不只仅须要安装webpack自己,还须要安装webpack-cli.
npm install webpack webpack-cli --save-dev
使用--save-dev
参数会将这两个包添加到package.json的开发依赖中.
在webpack4中能够实现0配置打包,也就是说不须要任何设置就能够完成简单的打包操做.
此外最实用的特性之一就是mode
配置选项用于告诉webpack输出模式是开发仍是产品,提供了已经预先定义好的经常使用配置.
后面的例子中咱们会使用到mode
.
咱们在当前目录下新建一个webpack的配置文件webpack.config.js.
此时的目录结构为:
learnwebpack
webpack.config.js的内容:
const {join:pathJoin} = require('path'); module.exports = { entry:{ app:'./src/index.js' // 入口文件的位置 }, output:{ filename:'[name].bundle.js', // 输出文件名字的格式 path:pathJoin(__dirname,'./dist') // 输出的绝对路径 }, }
对于咱们当前的应用来讲好像没有任何用途,打包后文件名彻底能够和入口同样.
使用不一样的文件名能够解决相同文件名称致使的浏览器缓存问题.
对于咱们当前这个格式来讲,打包后的文件名称为app.bundle.js
.
此外还有一些额外的模板符号:
如今让咱们在src文件夹下新建一个index.js,只写一行简单的代码用于测试:
console.log('hello world!');
此时的目录结构为:
learnwebpack
src
webpack4中零配置的默认入口位置就是当前配置路径下的./src/index.js
,也就是说若是不指定入口的状况下也是能够打包的.
运行:
./node_modules/.bin/webpack-cli --config webpack.config.js
上方的命令有点冗长,咱们使用package.json中scripts
字段来定义一个快捷方式.
package.json:
{ +++ "scripts": { "build": "webpack --config webpack.config.js" } +++ }
+++ 表示package.json
的其余字段,这部分目前不用关心.
如今运行这条简化的命令,效果和上方同样.
npm run build
对于npm版本高于5.2.0的同窗能够尝试使用npm的附带模块npx
.
npx能够直接运行./node_modules/.bin/
下的内容而没必要输入路径.
npx webpack --config webpack.config.js
若是操做正确你的目录下应该会多出一个dist文件夹,内部有一个app.bundle.js文件.
此时的目录结构:
learnwebpack
dist
src
咱们能够运行index.html了,若是一切顺利.那么在控制台中应该会出现hello world!
.
当咱们打包的时候webpack4会报错,缘由就是咱们没有指定上文中提到的mode
属性,webpack默认将他设置为production
.
此时若是你查看代码,就会发现代码是通过压缩的,这是webpack4的默认行为之一.
WARNING in configuration The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment. You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/concepts/mode/
使用npm安装:
npm -i vue
vue是运行时依赖,webpack须要合适loader将vue文件解释为webpack能够理解的格式用于构建,因此咱们须要vue-loader
来转换vue单文件.
使用npm安装vue-loader:
npm install vue-loader --save-dev
vue单文件中分为三个部分,其中template
部分须要专用的插件进行转换.
安装vue-template-compiler
:
npm install vue-template-compiler --save-dev
这个使用vue-loader自动调用的插件,也是官方默认的,不须要任何配置.
若是你不使用他,打包的时候会报错.
简单来讲他的功能是将template
部分的模板转为render
函数.
而后咱们须要处理css,vue-loader须要css-loader才能够运行.
安装css-loader:
npm install css-loader --save-dev
css-loader的做用仅仅是将css转为webpack能够解释的类型,若是咱们须要将样式使用起来插入到html中,必须使用额外的插件.
安装vue-style-loader
:
npm install vue-style-loader --save-dev
vue-style-loader
是由vue官方维护的你也可使用其余的loader来处理css,他除了提供了常见的插入样式到html的功能之外还提供了其余的功能,例如热更新样式等.
webpack.config.js:
const {join:pathJoin} = require('path'); const VueLoaderPlugin = require('vue-loader/lib/plugin'); // +++ module.exports = { mode:'production', entry:{ app:'./src/index.js' }, output:{ filename:'[name].bundle.js', path:pathJoin(__dirname,'./dist') }, module: { rules: [ { test: /\.vue$/, use: ['vue-loader'] // +++ }, { test: /\.css$/, use: ['vue-style-loader','css-loader'] // +++ } ] }, plugins:[ new VueLoaderPlugin() // +++ ] }
须要注意的是VueLoaderPlugin
在vue-loader
v15的版本中,这个插件是必须启用的.
咱们在src
下建立一个pages
文件夹而且在内部建立一个app.vue
文件.
此时的目录结构:
learnwebpack
dist
src
pages
app.vue文件内容:
<style> .test > p { background-color: aqua; } </style> <template> <article class="test"> <p>{{vue}}</p> </article> </template> <script> export default { data() { return { vue: "vue" }; } }; </script>
app.vue是由index.js引用的,回过头来咱们修改index.js:
import Vue from 'vue' import App from './pages/app.vue'; new Vue({ el:'#root', render:h=>h(App) })
激动人心的时候到了,若是一切顺利你的vue应用应该打包完成了,运行index.html就能够查看这个结果了.
回顾前面的一个话题,指定输出文件名字格式.若是你将咱们的内容放到一个服务器上运行,你会很容易发现一个问题.
就是缓存,web上的资源浏览器会对其进行缓存,可是对开发的时候,或者产品中的代码更新十分不友好,新的代码不会获得及时的使用.
咱们让资源每次的名字不同就能够简单的解决这个问题,接下来修改咱们的webpack.config.js
:
const {join:pathJoin} = require('path'); const VueLoaderPlugin = require('vue-loader/lib/plugin'); module.exports = { +++ output:{ filename:'[name].[hash].js', path:pathJoin(__dirname,'./dist') }, +++ }
此时再次修改代码打包每次的名字都不会同样.
可是出现了另一个问题因为资源名字每次都不一致,每次我都须要手动指定index.html中引用的资源,这个时候该html-webpack-plugin
出场了.
这个插件能够自动生成一个html文件,而且将资源文件按照正确顺序插入到html中.
安装html-webpack-plugin
:
npm install html-webpack-plugin --save-dev
webpack.config.js添加配置
const {join:pathJoin} = require('path'); const VueLoaderPlugin = require('vue-loader/lib/plugin'); const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { entry:{ app:'./src/index.js' }, output:{ filename:'[name].[hash]].js', path:pathJoin(__dirname,'./dist') }, module: { rules: [ { test: /\.vue$/, use: ['vue-loader'] }, { test: /\.css$/, use: ['vue-style-loader','css-loader'] } ] }, plugins:[ new HtmlWebpackPlugin({ template:'template.html',// 指定模板html文件 filename:'index.html'// 输出的html文件名称 }), new VueLoaderPlugin() ] }
而后咱们把index.html
重命名为template.html
,将template.html
中的script
标签删除.
指定模板后HtmlWebpackPlugin会保留原来html中的内容,并且会在新生成的html文件中把script插入到合适的位置.
注意:HtmlWebpackPlugin
必须位于插件数组的首位.
你会发如今dist目录下会有index.html文件,而咱们打包后的index.js的输出文件名也变成了app.XXXXXXXXXXXXXXXX.js
的格式,更加神奇的是在index.html中自动插入了script标签来引用打包后的js文件.
当你屡次打包的时候,你会发现因为使用hash来命名输出的文件每次的文件名称都不同,致使文件愈来愈多.
使用CleanWebpackPlugin能够每次构建前清空输出目录.
安装:
npm install clean-webpack-plugin --save-dev
webpack.config.js:
const {join:pathJoin} = require('path'); const VueLoaderPlugin = require('vue-loader/lib/plugin'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const CleanWebpackPlugin = require("clean-webpack-plugin");// +++ module.exports = { entry:{ app:'./src/index.js' }, output:{ filename:'[name].[hash]].js', path:pathJoin(__dirname,'./dist') }, module: { rules: [ { test: /\.vue$/, use: ['vue-loader'] }, { test: /\.css$/, use: ['vue-style-loader','css-loader'] } ] }, plugins:[ new HtmlWebpackPlugin({ template:'template.html', filename:'index.html' }), new VueLoaderPlugin(), new CleanWebpackPlugin(['dist'])// +++ 运行前删除dist目录 ] }
如今不管运行几回构建dist目录下都是干净的.
如今咱们来将vue单文件中的css提取出来到一个单独的css文件中.
webpack4中完成这个功能的插件是mini-css-extract-plugin
.
安装:
npm install mini-css-extract-plugin --save-dev
webpack.config.js:
const {join:pathJoin} = require('path'); const VueLoaderPlugin = require('vue-loader/lib/plugin'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const CleanWebpackPlugin = require("clean-webpack-plugin"); const MiniCssExtractPlugin = require('mini-css-extract-plugin');// +++ module.exports = { entry:{ app:'./src/index.js' }, output:{ filename:'[name].[hash]].js', path:pathJoin(__dirname,'./dist') }, module: { rules: [ { test: /\.vue$/, use: ['vue-loader'] }, { test: /\.css$/, use: [ { loader:MiniCssExtractPlugin.loader // +++ }, 'css-loader' ] } ] }, plugins:[ new HtmlWebpackPlugin({ template:'template.html', filename:'index.html' }), new MiniCssExtractPlugin({ filename:'style.css' // 指定输出的css文件名. }), new VueLoaderPlugin(), new CleanWebpackPlugin(['dist']) ] }
运行咱们的项目,如今dist目录下已经有一个style.css的文件了,并且htmlwebpackplugin自动将style.css插入到了index.html中.
考虑如下问题:
是时候使用多个配置了,一个用于开发一个用于生产.
可是咱们还能够作的更好使用webpack-merge
插件,能够将多个配置合成.
安装webpack-merge
:
npm install webpack-merge --save-dev
首先咱们定义一个包含基本信息的webpack配置文件,这个文件被其余配置文件依赖.
webpack.common.js:
const {join:pathJoin} = require('path'); const CleanWebpackPlugin = require("clean-webpack-plugin"); const VueLoaderPlugin = require('vue-loader/lib/plugin'); const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { entry:{ app:'./src/index.js' }, output:{ filename:'[name].[hash].js', path:pathJoin(__dirname,'./dist') }, plugins:[ new HtmlWebpackPlugin({ template:'template.html', filename:'index.html' }), new VueLoaderPlugin(), new CleanWebpackPlugin(['dist']) ] }
能够看到这里定义的都是最基本的信息.
而后咱们定义开发配置而且在内容使用webpack-merge
插件和webpack.config.js进行合并.
webpack.dev.js:
const merge = require('webpack-merge'); const common = require('./webpack.common.js'); module.exports = merge(common, { mode: 'development', // 不压缩代码,加快编译速度 devtool: 'source-map', // 提供源码映射文件调试使用 module: { rules: [ { test: /\.vue$/, use: ['vue-loader'] }, { test: /\.css$/, use: ['vue-style-loader','css-loader'] // 使用vue-style-loader直接插入到style标签中 } ] }, })
定义生产配置.
webpack.prod.js:
const merge = require('webpack-merge'); const common = require('./webpack.common.js'); const MiniCssExtractPlugin = require('mini-css-extract-plugin') module.exports = merge(common,{ mode:'production', // 压缩代码 module: { rules: [ { test: /\.vue$/, use: ['vue-loader'] }, { test: /\.css$/, use: [ { loader:MiniCssExtractPlugin.loader // 提取css到外部文件中 }, 'css-loader' ] } ] }, plugins:[ new MiniCssExtractPlugin({ filename:'style.css' }) ] })
最后修改一下咱们package.json中的快捷方式:
+++ "scripts": { "dev": "webpack --config webpack.dev.js", "build": "webpack --config webpack.prod.js" }, +++
删除以前的webpack.config.js.
完成后的目录结构:
learnwebpack
src
pages
尝试运行npm run dev
和npm run build
吧.
咱们在index.js中引用了Vue,若是你查看打包后的代码你会发现vue自己会被打包到同一个文件中,若是咱们有另一个文件也引用了vue一样的会被打包到该文件中.
显然咱们的代码依赖vue,可是vue不该该存在两份,若是能够将vue单独提取出来就行了,这个问题就是要代码分离.
在webpack4中删除了原来的CommonsChunkPlugin插件,内部集成的optimization.splitChunks选项能够直接进行代码分离.
修改webpack.dev.js:
const merge = require('webpack-merge'); const common = require('./webpack.common.js'); module.exports = merge(common, { mode: 'development', devtool: 'source-map', optimization:{ // +++ splitChunks:{ // +++ chunks:'initial' // +++ initial(初始块)、async(按需加载块)、all(所有块) } }, module: { rules: [ { test: /\.vue$/, use: ['vue-loader'] }, { test: /\.css$/, use: ['vue-style-loader','css-loader'] } ] }, })
咱们要作的就是将打包后写入到index.html的文件从目前的一个文件拆分红多个,而且写入到index.html中.
也就是说在入口处分离代码.
运行:
npm run dev
你会发如今dist目录下多出了一个文件保存着vue,另一个文件中保存着咱们编写的代码.
vue部分:
https://cn.vuejs.org/v2/guide...
https://vue-loader.vuejs.org/zh/
https://www.npmjs.com/package...
webpack部分:
https://webpack.docschina.org...
https://github.com/webpack-co...
https://github.com/jantimon/h...
参考的其余教程:
https://segmentfault.com/a/11...
https://segmentfault.com/a/11...
http://www.cnblogs.com/anani/...
https://blog.csdn.net/bubblin...