cnpm安装webpack_【6000字】从0到1,配置webpack
前言
随着前端工程化,webpack
已经是必不可少的打包工具,然鹅,我们在日常工作中,都是使用vue-cli
等脚手架,0配置直接写业务代码,这个我个人是支持的,毕竟这样可以让同学萌更专注业务代码。
但是假如你想鹤立鸡群,让面试官眼前一亮,那么webpack
的配置,确实需要了解一下。
太久没有从0配置webpack
,也借这一篇文章,让自己温故知新吧~
假如本文有错误的地方,希望能指正?。
假如您是已经对webpack
十分熟悉的,那么你可以右上角关掉...
环境
webpack 4.43.0
版本node v12.16.1
版本
入门
注意了,我这里是使用cnpm
的,你们喜欢用npm
、yarn
都可以
cnpm i -D
为cnpm install --save-dev
的缩写,开发依赖cnpm i -S
为cnpm install --save
的缩写,运行依赖
简单解释一下什么是开发依赖
和运行依赖
开发依赖
devDependencies
,就是开发时候的依赖,例如loader
、plugin
等等,不会被打包的,在线上不需要的运行依赖
dependencies
,就是运行时候的依赖,例如vue
、axios
等,是会被打包上线的
说了那么多,终于可以下载webpack
了?
先下载全局webpack
(不全局安装也行,这里不做讨论,毕竟才入门,越简单越好)
-g
是global
的意思,全局安装
cnpm i -g webpack webpack-cli
新建一个项目目录,就叫demo
吧,进入该项目后输入命令
npm init
这个时候,会有一堆东西让你填写,括号内是默认值,一路回车即可
package name: (webpack)version: (1.0.0)description:entry point: (index.js)test command:git repository:keywords:author:license: (ISC)Is this OK? (yes)
假如你连回车都不想多按,自动选中所有默认值,那么你可以这样做?
npm init -y
这个时候demo
下有了一个package.json
文件,里面有我们刚刚一路回车选中的东西,我们先不用管这个文件
其实这个时候已经可以使用webpack
了,先感受一下真0配置
新建一个文件夹src
,在src
里面建一个index.js
文件
console.log("前端背锅侠");
然后在终端中执行webpack
指令
webpack
你会发现项目下多了两个文件夹dist
及node_modules
,打开dist
->main.js
,你会看到有一大堆代码(多了一大坨代码是由于webpack
做了模块化处理),并且最后有几个中文字前端背锅侠
?
恭喜你,打包成功
基础配置
在根目录新建一个webpack.config.js
,为啥叫这个名字呢?
打开webpack
源码你会发现webpack-cli/bin/config/config-yargs.js
里面的defaultDescription
,你会有惊喜,这里不做深入研究
const { resolve } = require('path');module.exports = {mode: 'development', // 开发模式,有两种模式production【生产模式】和development【开发模式】 entry: resolve(__dirname, './src/index.js'), // 入口文件 output: {filename: 'index.js', // 打包后的文件名称 path: resolve(__dirname, './dist'), // 打包后的目录 },};
删掉dist
文件,再执行webpack
在打包一次,发现又成功了,这个时候你可以切换mode
模式,感受一下生产模式
和开发模式
在这个配置上加上hash
值
const { resolve } = require('path');module.exports = {mode: 'development', // 开发模式,有两种模式production【生产模式】和development【开发模式】 entry: resolve(__dirname, './src/index.js'), // 入口文件 output: {filename: 'index[hash].js', // 打包后的文件名称 path: resolve(__dirname, './dist'), // 打包后的目录 },};
发现,文件名竟然改掉了,加了一大串hash
,并且发现,只有我们在改了src/index.js
的文件代码后,打包的文件名字才会发生改变。对的,这就是hash
的作用,只有文件发生改变的时候,hash
才会发生变化,这样就完美解决缓存问题了。
假如你不喜欢那么长的hash
你也可以这样配置index[hash:5].js
现在是打包js
,那么怎么看在页面上行不行呢?
webpack-dev-server
及html-webpack-plugin
在src
目录下新建index.html
文件,并且把基本东西填写好
cnpm i webpack-dev-server html-webpack-plugin -D
配置
// webpack.config.js
const { resolve } = require('path');const HtmlWebpackPlugin = require('html-webpack-plugin');module.exports = {mode: 'development', // 开发模式,有两种模式production【生产模式】和development【开发模式】 entry: resolve(__dirname, './src/index.js'), // 入口文件 output: {filename: 'index[hash:5].js', // 打包后的文件名称 path: resolve(__dirname, './dist'), // 打包后的目录 },devServer: {port: 3000, // 端口 progress: true, // 进度条 open: true, // 自动打开浏览器 compress: true, // 压缩 },plugins: [new HtmlWebpackPlugin({template: './src/index.html', // 模板目录 filename: 'index.html', // 打包后的文件 minify: {removeAttributeQuotes: true, // 删除双引号 collapseWhitespace: true, // 折叠空行 } }), ],};
这个时候我们需要在package.json
里面增加一点指令,方便我们操作
{ ... "scripts": { "dev": "webpack-dev-server", "build": "webpack" }, ...}
先执行
npm run dev
玩webpack
最不想看到的东西出现了...卧槽...报错了...???
但是不要慌,看看报错的内容...Error: Cannot find module 'webpack'
,找不到webpack
是的,还记得我们开始就是全局安装webpack
,而不是当前项目安装吗?
我们尝试在这个项目安装一下
cnpm i webpack webpack-cli -D
此时再运行,能完美自动打开浏览器,并且在控制台中显示了前端背锅侠
并且我这个时候,修改index.html
或者index.js
,浏览器会自动显示我们想要的东西...妈耶..太爽了?
我们再执行另外的指令
npm run build
dist
目录下的文件就是我们想要的东西!!!!?
那么,假如多页面多入口(一个HTML
对应一个以上JS
),咋搞?
同样html-webpack-plugin
可以帮我们解决
我们先在src
目录下新建test.html
及test.js
,并且在里面随便写的东西
// webpack.config.js
const { resolve } = require('path');const HtmlWebpackPlugin = require('html-webpack-plugin');module.exports = {mode: 'development',// 注意 entry: {index: resolve(__dirname, './src/index.js'),test: resolve(__dirname, './src/test.js'), },// 注意 output: {filename: '[name][hash:5].js',path: resolve(__dirname, './dist'), },devServer: {port: 3000,progress: true,open: true,compress: true, },// 注意 plugins: [new HtmlWebpackPlugin({template: './src/index.html',filename: 'index.html',chunks: ['index'], }),new HtmlWebpackPlugin({template: './src/test.html',filename: 'test.html',chunks: ['test'], }), ],};
为了更简洁更突出我修改的地方,我把一些注释及一些HtmlWebpackPlugin
的minify
删掉
三点需要注意的地方
entry
入口改为key/value
形式output
输出改为[name][hash:5].js
,name
就是你入口所命名的key
plugins
插件中new
了2个HtmlWebpackPlugin
,并且chunks
写入口所命名的key
这个时候再build
,你会发现,多入口文件已经实现
留给同学萌一个小实验,假如一个HTML
对应多个JS
,咋搞?
提示HtmlWebpackPlugin
里面的chunks
是一个数组哦!!?
不知道你们会不会觉得,每次build
之前都要手动删除dist
,感觉好繁琐,有好的办法解决吗?
答案是肯定的
clean-webpack-plugin
下载clean-webpack-plugin
cnpm i clean-webpack-plugin -D
// webpack.config.js
const { resolve } = require('path');const HtmlWebpackPlugin = require('html-webpack-plugin');const { CleanWebpackPlugin } = require('clean-webpack-plugin');module.exports = {mode: 'development',entry: resolve(__dirname, './src/index.js'),output: {filename: 'index[hash:5].js',path: resolve(__dirname, './dist'), },devServer: {port: 3000,progress: true,open: true,compress: true, },plugins: [new CleanWebpackPlugin(),new HtmlWebpackPlugin({template: './src/index.html',filename: 'index.html',minify: {removeAttributeQuotes: true,collapseWhitespace: true, }, }), ],};
其实就很简单,在plugins
中new CleanWebpackPlugin()
即可
css
我们在src
下新建一个index.css
并且写入一些样式,并且在index.js
中引入
import './index.css';console.log('前端背锅侠');
运行一下,npm run dev
,你会发现样式无效,并且控制台报错
这个时候就需要loader
来处理了
cnpm i style-loader css-loader -D
// webpack.config.js
const { resolve } = require('path');const HtmlWebpackPlugin = require('html-webpack-plugin');const { CleanWebpackPlugin } = require('clean-webpack-plugin');module.exports = {mode: 'development',entry: resolve(__dirname, './src/index.js'),output: {filename: 'index[hash:5].js',path: resolve(__dirname, './dist'), },devServer: {port: 3000,progress: true,open: true,compress: true, },plugins: [new CleanWebpackPlugin(),new HtmlWebpackPlugin({template: './src/index.html',filename: 'index.html',minify: {removeAttributeQuotes: true,collapseWhitespace: true, }, }), ],module: {rules: [ {test: /\.css$/,use: ['style-loader', 'css-loader'], // 从左往右解析 }, ], },};
我们重新再跑一遍npm run dev
,你会发现,样式生效了,并且审查元素的时候,发现样式在head
里面
当然,相信你们在工作中也不会纯写css
,肯定是sass
、less
或者stylus
我们用sass
举例
sass-loader
下载
cnpm i sass-loader node-sass -D
我们直接把index.css
改为index.scss
,并且在index.js
中修改引入的路径
// webpack.config.js
// 由于代码太长,我就不重复复制了
module: {rules: [ {test: /\.css$/,use: ['style-loader', 'css-loader'], }, {test: /\.(scss|sass)$/,use: ['style-loader', 'css-loader', 'sass-loader'], }, ],}
重新npm run dev
,效果也出来了
postcss-loader
及autoprefixer
如果我说,有loader
可以自动帮我们添加浏览器前缀,你会不会觉得样式兼容不再是个棘手的问题??
cnpm i postcss-loader autoprefixer -D
// webpack.config.js
module: {rules: [ {test: /\.(scss|sass)$/,use: ['style-loader','css-loader', {loader: 'postcss-loader',options: {plugins: [require('autoprefixer')], }, },'sass-loader', ], }, ],},
// package.json{ ... "browserslist": ["last 2 versions", "> 1%"]}
这里有其他的配置方式,这里不深入讨论
重新npm run dev
,看到css
的样式全部都加了后缀,真香~
样式抽离
mini-css-extract-plugin
如果样式很多,全部写在head
里面貌似也不是我们想要的,我们需要抽离
下载mini-css-extract-plugin
cnpm i mini-css-extract-plugin -D
// webpack.config.js
// 代码太长,省略了部分代码const MiniCssExtractPlugin = require('mini-css-extract-plugin');module.exports = {plugins: [new MiniCssExtractPlugin({filename: 'css/[name][hash:5].css', }), ],module: {rules: [ {test: /\.(scss|sass)$/,use: [/** * 注意,这里本来应该是style-loader * 但是由于我们现在不需要将css写在head,而是抽离 * 所以用MiniCssExtractPlugin.loader代替 */ MiniCssExtractPlugin.loader,'css-loader', {loader: 'postcss-loader',options: {plugins: [require('autoprefixer')], }, },'sass-loader', ], }, ], },};
引入图片
假如你没有相关配置,你是无法引入背景图片的,不信你试试??
body {background: url('images/img2.png');#test {display: flex;background: url('images/img.png');height: 100px;width: 100px;background-size: 100% 100%; }}
下载url-loader
cnpm i url-loader file-loader -D
// webpack.config.js
module: {rules: [ {test: /\.(jpe?g|png|gif)$/i,use: [ {loader: 'url-loader',options: {limit: 10 * 1024,outputPath: 'images',publicPath: "../images" }, }, ], } ],},
注意limit
是限制大小,如果图片小于10k
那么就将图片转为base64
从而减少请求,达到优化,但是假如图片大于10k
,那么转base64
还不如直接请求
通过上面配置后,你会发现,正如我所说的...?
当你觉得一切万事大吉的时候,你在HTML
上写上了这一句
<img src="./images/img2.png" alt="" />
又炸了...?
这个时候需要html-withimg-loader
来处理
cnpm i html-withimg-loader -D
// webpack.config.js
module: {rules: [ {test: /.html$/,use: 'html-withimg-loader', } ],},
当我愉快地以为这就可以的时候,我发现页面上一直404,经过多番查阅,才发现..原来有些file-loader
改了配置!!?
// webpack.config.js
module: {rules: [ {test: /.html$/,use: 'html-withimg-loader', }, {test: /\.(jpe?g|png|gif)$/i,use: [ {loader: 'url-loader',options: {limit: 10 * 1024,// 要在这里加上这一句 esModule: false,outputPath: 'images',publicPath: '../images', }, }, ], }, ],},
将
JS
转为兼容版本
我们先试试新语法打包出来的结果是咋样的
// index.js
const name = '前端背锅侠'
我们执行打包npm run build
,然后看dist
目录下的index.js
,在代码的最后部分发现了
eval("const name = '前端背锅侠'\n\n//# sourceURL=webpack:///./src/index.js?");
发现const
并没有被转到低版本
这个时候babel
出场了
cnpm i babel-loader @babel/core @babel/preset-env -D
我们重新build
一遍,发现dist
目录下的index.js
,发生了改变
eval("var name = '前端背锅侠';\n\n//# sourceURL=webpack:///./src/index.js?");
const
变成了var
但是不要高兴太早,当我们试试Promise
语法的时候,你就发现,并没有达到预期的效果
这个时候我们还需要另外一个东西@babel/polyfill
cnpm i @babel/polyfill -D
// webpack.config.js
// 入口文件修改entry: ['@babel/polyfill', resolve(__dirname, './src/index.js')],
我们试一下新的API
,试试效果
// src/index.js
Promise.resolve('前端背锅侠').then(console.log);
这个时候,你再build
一遍,你就发现,dist
目录下的index.js
,搜索一下前端背锅侠
,你会发现,貌似没有编译到低版本的语法呀??
其实已经是低版本的语法了,你认真比一下有没有加@babel/polyfill
打包出来的文件,大小都不一样。
你认真看打包后的文件,你会发现,原来babel
把新API
都用兼容语法重写了一遍!?
eslint
相信代码唐僧eslint
肯定在日常开发中,能帮你们团队解决了很多规范问题
cnpm i eslint eslint-loader -D
module: {rules: [ {test: /\.js$/,use: {loader: 'eslint-loader',options: {enforce: 'pre', // enforce强制的意思 pre(前面执行) post(后面执行) }, }, }, ],},
在根目录创建.eslintrc.js
module.exports = {env: {browser: true,es6: true,node: true, },parserOptions: {sourceType: 'module', },rules: {quotes: ['error', 'single'], },};
更多的eslint
规则,建议到eslint
官网,自己配置,这里我就只写一个单引号的规则
修改src
下的index.js
美丽的红色波浪线又出现了,唐僧啊~~?
如果你能看到这里,并且能跟着敲,那么你已经离成功就差一步了,加油,别放弃啊,骚年?
【基本配置】到此结束,接下来进入配置vue
的章节
配置vue
下载vue
相关的东西
cnpm i vue-loader vue-template-compiler vue-style-loader -Dcnpm i vue -S
我们就在上面的基础上继续搭建vue
先将src
下面的东西清空,然后新建以下文件
// src/index.js
import Vue from 'vue';import App from './App.vue';new Vue({el: '#app',render: (c) => c(App),});
<html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Documenttitle>head><body><div id="app">div>body>html>
// src/App.vue
{{ msg }}
回到webpack.config.js
const { resolve } = require('path');const HtmlWebpackPlugin = require('html-webpack-plugin');const { CleanWebpackPlugin } = require('clean-webpack-plugin');const MiniCssExtractPlugin = require('mini-css-extract-plugin');const VueLoaderPlugin = require('vue-loader/lib/plugin');module.exports = {mode: 'development',entry: ['@babel/polyfill', resolve(__dirname, './src/index.js')],output: {filename: 'index[hash:5].js',path: resolve(__dirname, './dist'), },devServer: {port: 3000,progress: true,open: true,compress: true, },plugins: [new CleanWebpackPlugin(),new HtmlWebpackPlugin({template: './src/index.html',filename: 'index.html',minify: {removeAttributeQuotes: true,collapseWhitespace: true, }, }),new MiniCssExtractPlugin({filename: 'css/[name][hash:5].css', }),new VueLoaderPlugin(), ],module: {rules: [ {test: /\.vue$/,use: ['vue-loader'], }, {test: /\.js$/,use: {loader: 'babel-loader',options: {presets: ['@babel/preset-env'], }, },exclude: /node_modules/, }, {test: /\.(jpe?g|png|gif)$/i,use: [ {loader: 'url-loader',options: {limit: 10 * 1024,esModule: false,outputPath: 'images',publicPath: '../images', }, }, ], }, {test: /\.(scss|sass)$/,use: [ MiniCssExtractPlugin.loader,'css-loader', {loader: 'postcss-loader',options: {plugins: [require('autoprefixer')], }, },'sass-loader', ], }, ], },};
虽然扔了一大坨代码上来,但是细心的你,肯定发现,其实就只是加了一个loader
和plugins
罢了
跑起来看看效果吧...
成功了...?
好的..本文就到这里结束了...写那么长的文章...真的累~
假如你webpack
真的不熟悉,个人建议你还是多敲几遍,自然你就熟悉了
其实还有很多配置没有说,例如:环境区分,别名配置、打包优化等等等,个人建议你还是多翻阅更多的资料,到webapck
的官网上面认真细读一下,不要做一个伸手党...
工作中,假如没有那么多时间配置webpack
,还是老老实实用脚手架吧?
本文属个人理解,如有错误,期待你的提出及交流,谢谢。
扫码进入前端交流群
扫码进入前端交流群
cnpm安装webpack_【6000字】从0到1,配置webpack相关推荐
- cnpm安装webpack_快速打造最强 Webpack 前端工具链
当前,前端技术日新月异,公司的团队技术栈和业务场景不同,都会建立自己的前端工程体系.一个好的工程体系能够保证团队的研发流程规范,提高团队的研发效率,能够减少人员流动带来的项目交接和维护成本.2-3个项 ...
- cnpm安装失败及解决方案
1.首先要去配置node.js,直接去node.js官网(http://nodejs.cn/) 下载node-vx.x.x.pkg文件双击一路默认安装即可,安装完在终端输入: node -v 如果显示 ...
- java实训感想6000字_JAVA论文6000字:无线校园
论文最好能建立在平日比较注意探索的问题的基础上,写论文主要是反映学生对问题的思考, 详细内容请看下文JAVA论文6000字. 随着网络应用日益丰富,传统局域网络已经不能满足师生对移动网络的要求,无线局 ...
- Oracle Linux 6.9安装和Oracle 11.2.0.4.0安装及psu补丁升级
原文有图图https://www.linuxidc.com/linux/2018-09/154218.htm 图文详解在Oracle Linux 6.9安装和Oracle 11.2.0.4.0安装及p ...
- 无法安装或运行此应用程序。该应用程序要求首先在“全局程序集缓存(GAC)”中安装程序集stdole版本7.0.3300.0...
无法安装或运行此应用程序.该应用程序要求首先在"全局程序集缓存(GAC)"中安装程序集stdole版本7.0.3300.0 2011年12月21日 windows系统中目录 win ...
- 使用cnpm安装 React
React 17.0.1 安装 使用cnpm安装react $ cnpm install -g create-react-app$ create-react-app react-learning$ c ...
- 前端开发之cnpm安装总是失败--已解决
租了一台新电脑,之前电脑开发实在是太卡了,对于做前端开发的小伙伴nodejs,cnpm啥的肯定是必装.其他还好,安装完nodejs后执行node -v +npm -v都是正常的,接下来就该安装cnpm ...
- tensor搭建--windows 10 64bit下安装Tensorflow+Keras+VS2015+CUDA8.0 GPU加速
windows 10 64bit下安装Tensorflow+Keras+VS2015+CUDA8.0 GPU加速 原文见于:http://www.jianshu.com/p/c245d46d43f0 ...
- Ubuntu14.04 64位机上安装OpenCV2.4.13(CUDA8.0)版操作步骤
Ubuntu14.04 64位机上安装CUDA8.0的操作步骤可以参考http://blog.csdn.net/fengbingchun/article/details/53840684,这里是在已经 ...
最新文章
- 【微读书】《人工智能颠覆未来战争》连载之一:机器战胜人类?——AlphaGo人机对战的启示...
- 2021年信号与系统处理期中考试与课堂交互分数
- 2020-11-05 关于前端‘古董‘dojo的树结构如何默认展开根节点
- [原] 探索 EventEmitter 在 Node.js 中的实现
- Callable和Future接口的实现
- Swoole的think-swoole的安装
- python语言变量随时声明_2. Go语言五种变量创建的方法
- HTTPS协议详解:TLS/SSL握手过程
- 访问受限 诺基亚禁止Navifirm获取固件(图)
- Python中用冒号表达式对列表切片
- SM4算法 C语言 (从OpenSSL库中分离算法:七)
- AD9361射频捷变收发器系列对比
- 【PS | 学习】毛坯乡间图打造复古美式电影海报图
- 前端必知必会的技术体系,再也不担心前端内卷了
- 小学语文思维导图免费模板合集!家长必收藏
- BZOJ 2339 【HNOI2011】 卡农
- [原创]网站文章页面添加分享按钮,百度按钮代码复制使用时不显示问题解决!
- 概述纵横制电话交换机
- 全球与中国汽车空气悬架系统市场现状及未来发展趋势
- 信噪比SNR、符号信噪比Es/N0与比特信噪比Eb/N0的关系