目录
npm
package.json
常见的属性
main属性
scripts属性
dependencies属性
devDependencies属性
其他属性
依赖版本管理
package-lock.json
npm install 原理
npx
webpack
内置模块path编辑
基本使用
css-loader
postcss-loader
postcss-preset-env
webpack打包图片
label
vue-loader
resolve:extensions
插件plugin
CleanWebpackPlugin
HtmlWebpackPlugin
DefinePlugin
webpack搭建本地服务器
模块热替换HMR
pnpm
基本介绍
硬链接和软链接
pnpm创建 非扁平化node_moduls目录
基本使用
最基本的用法与npm对照
pnpm存储
npm
node package manger
npm install XXX
使用npm安装,会生成一个node_modules文件夹,然后将下载的东西放进去
除了这个文件夹,还有两个文件package-lock.json package.json
package.json
对于一个完整的项目来说,我们需要一个配置文件来记录这个项目的一些信息,例如项目名字,项目版本号,项目依赖的库等等
这个配置文件就是我们的package.josn
第一种方法就是直接在cmd中输入 npm init 就可以,它会一步一步提示你完成
内容大概有
{"name": "why","version": "1.0.0","description": "","main": "mian.js","scripts": {"test": "echo \"Error: no test specified\" && exit 1"},"author": "","license": "ISC"
}
第二种方法是脚手架CLI
常见的属性
main属性
之前说过,如果在js文件中直接引用const name = require('why'),它会先在该文件上一层文件中找node_modules文件夹,然后在里面找why文件夹,再在下面找index.js
但是如果why文件夹下面不是index.js,显然就会报错
如果why文件夹下面有一个main.js(反正不叫index.js),但是还有一个package.json,那么就会先读取这个package.json,看看里面是否有main属性,然后通过这个mian属性找到why文件夹入口,就可以指定运行 这个不叫index.js的文件
package.json(),根据这个mian的内容决定要从哪里开始运行,注意这个文件是放在why文件夹下的
{"name": "why","version": "1.0.0","description": "","main": "mian.js","scripts": {"test": "echo \"Error: no test specified\" && exit 1"},"author": "","license": "ISC"
}
scripts属性
对于这个文件夹
如果在根目录learn下,我想运行src下的main.js,那么我得输入node src/main.js
但是在learn文件夹下的package.json中的scripts写入
"scripts": {"start": "node ./src/main.js","test": "echo \"Error: no test specified\" && exit 1"//这个是自带的},
那么只需要输入npm run start就可以运行src下的main.js
dependencies属性
dependencies记录了依赖的包
在真实开发中,如果想要共享代码给别,一般不会把node_modules文件夹压缩给别人,因为可能这个文件夹很大,不方便压缩发送
那么可以利用 dependencies属性,只需要输入 npm install 就可以下载所有依赖的包
devDependencies属性
开发依赖
也就是说一些包 ,只是在开发过程中用到了,在之后的使用过程中不需要了,例如webpack,我们只需要在开发时用他进行打包,打包完之后就不需要了
那么在下载的时候就需要对其进行声明
npm install XXX --save-dev 或者 npm install XXX -D
其他属性
依赖版本管理
package-lock.json
记录使用的包的具体版本(精确的版本),以防止代码共享时的版本混乱的问题
npm install 原理
npx
如果使用npm install webpack 安装包之后
包都是安装在在node_modules下,这个时候在控制台输入webpack --version,会找不到,因为它不会往下查找,只会在learn文件夹下找是否有webpack,而不会进入node_modules
如果它找不到,就会去全局找webpack,如果想在全局下安装包,应该使用npm i webpack -g
如果使用npx webpack --version就可以在node_modules找到对应的版本
同样的 如果要使用包 例如webpack,如果直接输入webpack执行,则会执行全局版本(如果没有全局版本则报错),如果使用npx webpack则会使用node_modules下的版本
但是 ,如果在package.json中的script中建立 "built":"webpack" 那么直接在控制台输入 npm run built 是ok的,会直接使用node_modules下的版本
webpack
内置模块path
直接使用即可 不需要下载
const path = require('path')
const file = 'C:/aaa/bbb/ccc.txt'
console.log(path.basename(file));
console.log(path.dirname(file));
console.log(path.extname(file));
ccc.txt
C:/aaa/bbb
.txt
路径拼接
const file1 = '../why/ccc.js'
const file2 = 'C:/aaa/bbb/'
console.log(path.join(file2,file1));
C:\aaa\why\ccc.js
拼接的绝对路径
这个方法一定会返回绝对路径,如果没有找到,则以当前文件的路径进行拼接
console.log(path.resolve('abc/sss','qsa.ww','sdd/ss.txt'));
L:\XXXXXX\src\abc\sss\qsa.ww\sdd\ss.txt
顺序是从右到左,如果找到了绝对路径就会立即输出,/ 看成就是绝对路径的标志
console.log(path.resolve('abc/sss','/qsa.ww','sdd/ss.txt'));
L:\qsa.ww\sdd\ss.txt
基本使用
概念 | webpack 中文文档
在开发过程中会用到很多包或者框架,例如vue,在编写的时候为了方便可能会有许多奇奇怪怪的文件,比如.vue .jxs等等,但是这些东西服务器和浏览器是不认识的
所以需要打包工具将所有东西打包为html css js
下载需要webpack 与 webpack-cil一起下载
npm i webpack webpack-cil -D
一般来说直接在命令行输入 npx webpack 就可以 生成一个dist文件夹,此文件夹下面是main.js
我在运行这里的时候遇到一个bug,说是找不到src文件夹,显然运用webpack打包时需要把js文件放在src文件夹下,js文件的名字是index.js,且此名称是固定的
上述的文件名都是默认配置,如果想改变这些,可以自己定义一个webpack配置文件
在project文件夹下创建 webpack.config.js 文件,然后还是直接npx webpack,当然如果你不想叫 webpack.config.js ,那么可以 npx webpack --config xxxx.js
const path = require('path')module.exports = {entry:'./src/main.js',//导入文件的路径output:{filename:'aaa.js',//输出文件名path:path.resolve(__dirname,'./ccc')//输出的文件夹名字,必须为绝对路径}
}
可以定义打包的文件输入接口,还有打包的输出
css-loader
webpack在打包时很多文件是不认识的,初始只认识js文件,当他碰到不认识的文件,例如.css文件 .vue文件时,就需要被告知解析这种文件需要什么方法,也就是需要什么loader
这些信息都在config.js中配置
const path = require('path')module.exports = {entry:'./src/main.js',//导入文件的路径output:{filename:'aaa.js',//输出文件名path:path.resolve(__dirname,'./ccc')//输出的文件夹名字,必须为绝对路径},module:{rules:[{test:/\.css$/, //正则 以.css结尾use:[{loader:'style-loader'},//从后往前执行{loader:'css-loader'}]}]}
}
这里主要是增加了model模块
rules是对文件的解析规则进行了声明
test表示匹配,这里采用正则表达式,也就是说当匹配到以 .css文件结尾的文件时才会执行这个规则
use表示匹配成功后的解析规则,这里用到了两个loader,分别是css-loader,这个是将css文件进行解析,是第一步,第二步是将css代码部署到html中,用到的是style-loader,由于这里是从后往前执行的,所以先写style-loader
一般来说,会在初级文件夹下建立component文件夹放js文件,style文件夹下放css文件
然后在component文件夹下js的文件引入css文件
import '../style/ddiv.css'
最后在src文件夹下面的main.js文件下引入js文件
import '../component/ddiv.js'
这样的目的是在打包时,webpack能顺着 main.js ->js->css 一路搜索到文件并进行打包
less文件类似
rules:[{test:/\.css$/, //正则 以.css结尾use:[{loader:'style-loader'},{loader:'css-loader'}]},{test:/\.less$/,use:['style-loader','css-loader','less-loader']}]
postcss-loader
对css进行一些处理的loader
例如autoprefixer ,可以自动给某些css语句加浏览器前缀
用法:
例如我在css中添加user-select,这个属性是有限制的,一般要加浏览器前缀,可以使用autoprefixer自动添加
当然这个插件需要下载 npm i autoprefixer -D
.content{width: 100px;height: 100px;background-color: pink;user-select: none;
}
先在webpack.config.js写
{test:/\.css$/, //正则 以.css结尾use:['style-loader','css-loader','postcss-loader']},
然后在根目录下新建文件 postcss.config.js
module.exports = {plugins: ['autoprefixer']
}
也可以直接在webpack.config.js写
{test:/\.css$/, //正则 以.css结尾use:[{loader:'style-loader'},{loader:'css-loader'},{loader:'postcss-loader',options:{postcssOptions:{plugins: ['autoprefixer']}}}]},
postcss-preset-env
也就是说这个东西集成了很多插件预设,使用这个就可以使用很多功能(推荐)
{test:/\.css$/, //正则 以.css结尾use:[{loader:'style-loader'},{loader:'css-loader'},{loader:'postcss-loader',options:{postcssOptions:{plugins: ['postcss-preset-env']}}}]},
webpack打包图片
js文件:
import '../style/ddiv.css'
import girlImg from '../img/aaa.png'//导入图片const imgg = document.createElement('img')
// imgg.classList.add('content')
imgg.src = girlImg
document.body.append(imgg)
在webpack.config.js中配置:
{test:/\.(png|jpg|jpeg|svg|gif)$/,type:'asset'}
type有四种,对应四种解析方式
第一种 asset/resource 会将原图片下载下来重命名放到打包文件中
缺点是需要一次网络请求才能完成图片嵌入
第二种 asset/inline 会见图片进行base64直接嵌入到js中,缺点是导致js文件很大
可以规定图片大小
{test:/\.(png|jpg|jpeg|svg|gif)$/,type:'asset',parser: {dataUrlCondition: {maxSize: 4 * 1024 // 4kb}}}
还可以自定义输入文件名
{test:/\.(png|jpg|jpeg|svg|gif)$/,type:'asset',parser: {dataUrlCondition: {maxSize: 4 * 1024 // 4kb}},generator: {filename: 'abc.png'}}
一般会使用
filename: '[name]_[hash:8][ext]'
表示 [原来的名字]_[保留8位哈希值][原来的后缀名]
这些属性都可以通过查官方文档得到
资源模块 | webpack 中文文档
label
Babel,又名Babel.js。 是一个用于web 开发,且自由开源的JavaScript 编译器、转译器。 Babel 使软件开发者能够以偏好的编程语言或风格来写作源代码,并将其利用Babel 翻译成JavaScript。 Babel 是一个常用来使用最新的JavaScript 语言特性的工具。——维基百科
其实说白了就是将es6 等有浏览器兼容问题的高级语法转换为es5语法
当然与postcss-loader相似,这个也有很多插件,一般用预设插件
npm i babel-loader -D
npm i @babel/preset-env -D
{test:/\.js$/,use:[{loader:'babel-loader',options:{presets: [['@babel/preset-env']]}}]}
vue-loader
const path = require('path')
const {VueLoaderPlugin} = require('vue-loader/dist/index')module.exports = {entry:'./src/index.js',//导入文件的路径output:{filename:'aaa.js',//输出文件名path:path.resolve(__dirname,'./ccc')//输出的文件夹名字,必须为绝对路径},module:{rules:[{test:/\.vue$/,use:[{loader:'vue-loader'}]}]},plugins:[new VueLoaderPlugin()]
}
const {VueLoaderPlugin} = require('vue-loader/dist/index')
是必须的,将插件引入最后在plugins使用插件
resolve:extensions
在使用require导入文件时,如果后缀名是.js 或者.json,就可以不需要加后缀名,因为webpack会自动补齐
这里是因为其内部有resolve:extensions规则,也可以自己设定自动补齐的文件格式
在webpack.config.js中加入
resolve:{extensions:['.js','.json','.vue','.jsx','.tx','.tsx']},
也就说在reuqire这六种文件的时候可以不需要加后缀名
插件plugin
CleanWebpackPlugin
添加插件的方式
先下载插件 npm i clean-webpack-plugin -D
在webpack.config.js中引入插件
const {CleanWebpackPlugin} = require('clean-webpack-plugin')
最后配置 ,类似于vue-loader中插件的用法
plugins:[new CleanWebpackPlugin(),],
这个插件的作用是在打包时自动删除其他没用的文件
例如在打包后的导入的文件夹ccc下手动创造一个文件,那么在重新打包后会把这个文件删除,因为这个文件跟打包是没有关系的
HtmlWebpackPlugin
是一个能在打包时生成html文件的插件
引入方式一样
const HtmlWebpackPlugin =require('html-webpack-plugin')
plugins:[new CleanWebpackPlugin(),new HtmlWebpackPlugin(),],
生成html的title是自带的,也可以自己设置
new HtmlWebpackPlugin({title:'XXXX'}),
这里的html是新生成的,其原理是用到了一个自带的模板,如果想自己改为其他的模板,可以:
new HtmlWebpackPlugin({title:'XXXX',template:'./index.html'}),
DefinePlugin
这个不需要下载,是webpack里面自带的
可以设置全局变量,在任何地方都可以使用
const {DefinePlugin} = require('webpack')
在plugins中:
new DefinePlugin({base:"'why'",hhh:'123'})
这里就指定了两个全局变量 base 和 hhh
这里base需要两个引号的原因是,如果只有一个引号,那么会将引号内的看做js代码执行,例如我写 base:"1+1",我的本意是将base定义为字符串 1+1 ,但是这里会自动执行,使得base定义为2
如果 base:“why”,那么默认是将why这个变量传给base
webpack搭建本地服务器
之前的操作中,如果我们改变了代码,那么每次都要重新打包运行,才能看到运行结果,这种开发效率很慢
可以使用webpack-dev-server插件自己搭建一个本地服务器,可以做到每次改变代码可以自动打包运行显示,提升了开发效率
且其自动打包不会再生成打包文件,即不讲打包文件放在硬盘中,而是将其放在内存中,以提升运行速度
首先下载
npm i webpack-dev-server-D
然后直接在命令行运行
npx webpack serve
从第一个8080端口进去,就是本地的服务器创造的html
每次改变代码,保存即可自动刷新
当然也可以直接设定端口地址
在webpack.config.js里面写
devServer:{port:8888},
模块热替换HMR
手动设置这个有点麻烦 ,一般框架是会自动设置这个的,做个了解就行了
pnpm
基本介绍
首先上述方法有一个痛点
如果我电脑里面有很多个project,每个里面都用到了很多包,例如vue等等,有很多包是重复的
但是按照上面的方法,需要每个project都去安装对应的包,这会造成浪费
pnpm解决了这个问题
硬链接和软链接
首先说一下硬链接和软链接的关系
硬链接是多个文件同时指向同一个硬盘数据,(不是拷贝)
软链接是创造一个文件A,此文件放的是另外一个文件B的路径,B指向硬盘数据,最典型的是快捷方式
那pnpm就是可以创建硬链接
当我有很多工程都用到了同一个包时,例如vue,pnpm会为每一个工程创造一个硬链接指向硬盘中的vue文件,所以不管怎么增加工程,vue文件在硬盘中始终只有一个
pnpm创建 非扁平化node_moduls目录
使用npm安装包的时候,会将所有的包都放在node_moduls文件夹下
例如这里我只安装了一个webpack,但是文件夹里面有很多其他包,是因为webpack包还依赖于其他的包,例如ajv,这就是扁平化 node_moduls目录
这样有什么问题呢
那就是我在引入的时候,可以在代码直接引入 ajv包,这样是有问题的,因为我只下载了webpack包,且package.json里面并没有包含ajv包的信息。理所当然的我希望只能引用webpack包才对
所以pnpm引入非扁平化 node_moduls目录
使用 pnpm add webpack 下载
可以发现其node_modules下没有一堆文件了,webpack的依赖包都放在了webpack文件夹下
但是这里的webpack文件夹是一个快捷方式(软链接),真实文件在.pnpm文件夹下:
然后在这个文件夹下还有一个node_modules ,放入webpack本身的硬链接,还有依赖包的软链接,依赖包的真实文件也在.pnpm文件夹下,以此类推
基本使用
最基本的用法与npm对照
pnpm存储
使用pnpm添加包,会给每个工程创建一个硬链接,其是pnpm也会创造一个硬链接,用于记录已经下载过了那些包
这个文件一般是叫 pnpm-store
这里有一个问题,如果有一个包,之前用过,后面把项目删除了, pnpm-store里面的硬链接是不会删除的,这会造成空间浪费
使用pnpm store prune裁剪