javascript包管理工具npm、pnpm、webpack

目录

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

 手动设置这个有点麻烦 ,一般框架是会自动设置这个的,做个了解就行了

最后把上述说到的所有webpack.config.js文件内容放在这里

const path = require('path')
const {CleanWebpackPlugin} = require('clean-webpack-plugin')
const HtmlWebpackPlugin =require('html-webpack-plugin')
const {VueLoaderPlugin} = require('vue-loader/dist/index')
const {DefinePlugin} = require('webpack')

module.exports = {
    mode:'development',
    entry:'./src/main.js',//导入文件的路径
    output:{
        filename:'aaa.js',//输出文件名
        path:path.resolve(__dirname,'./ccc')//输出的文件夹名字,必须为绝对路径
    },
    plugins:[
        new CleanWebpackPlugin(),
        new HtmlWebpackPlugin({
            title:'XXXX',
            template:'./index.html'
        }),
        new VueLoaderPlugin(),
        new DefinePlugin({
            base:"'why'",
            hhh:'123'

        })
    ],
    module:{
        rules:[
            {
                test:/\.css$/,  //正则  以.css结尾
                use:[
                    {loader:'style-loader'},
                    {loader:'css-loader'},
                    {loader:'postcss-loader',options:{
                        postcssOptions:{
                            plugins: [
                                'postcss-preset-env'
                            ]
                        }
                    }}
                ]
            },
            {
                test:/\.less$/,
                use:['style-loader','css-loader','less-loader']
            },
            {
                test:/\.(png|jpg|jpeg|svg|gif)$/,
                type:'asset',
                parser: {
                    dataUrlCondition: {
                      maxSize: 4 * 1024 // 4kb
                    }
                  },
                  generator: {
                    filename: '[name]_[hash:8][ext]'
                  }
            },
            {
                test:/\.vue$/,
                use:[
                    {loader:'vue-loader'}
                ]
            }
        ]
    },
    devServer:{
        port:8888
    },
    resolve:{
        extensions:['.js','.json','.vue','.jsx','.tx','.tsx']
    },
}

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裁剪

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值