webpack从零搭建开发环境

2020-09-21 11:10:46 浏览数 (1)

什么是 webpack

使用 webpack 作为前端构建工具

  • 代码转化:TypeScript编译成Javascript,SCSS编译成Css
  • 文件优化:压缩JavaScriptCssHtml代码 压缩合并图片等
  • 代码分割:提取多个页面的公共代码 提取首屏不需要执行部分的代码让其异步加载
  • 模块合并:在采用模块化的项目会有很多个模块和文件,需要构建功能把模块分类合并成一个文件
  • 自动刷新:监听本地源代码的变化,自动重新构建,刷新浏览器
  • 代码校验:在代码被提交到仓库前需要校验代码是否符合规范,以及单元测试是否通过
  • 自动发布:更新完代码后,自动构建出线上发布代码并传输给发布系统

在 webpack 应用中有两个核心

  • 模块转换器:用于把模块原内容按照需求转换成新内容,可以加非 JS 模块
  • 扩展模块:在 webpack 构建流程中的特定时机注入扩展逻辑来改变构建结果或做 NIIT 想要的事情

初始化项目

代码语言:javascript复制
npm init -y
npm i webpack webpack-cli --save-dev
代码语言:javascript复制
npm -S 是--save的缩写  是生产
npm -D 是--save-dev的缩写  是开发

webpack-cli 的目的是解析用户传递一些参数给 webpack 打包

打包

  • webpack 默认支持模块的写法 commonJs 规范是 Node
  • 也支持 es6 规范 esmodule
  • 把模块打包,解析出浏览器可以识别的代码
  • webpack 的时候是装的开发环境 直接 webpack 是找不到的,可以使用 npx (这个命令是 npm 5.2) 之后出来的 npx 是默认找 node_modules 中的.bin 目录下的文件
代码语言:javascript复制
  npx webpack
  • 两种模式:开发环境 生产环境
代码语言:javascript复制
  npx webpack --mode development  开发环境不会被压缩

为了方便也可以这么写,使用 npm run 命令这个命令执行的时候默认会把 node_modules 的.bin 文件放到全局上,执行之后销毁npm run buildnpm run dev

代码语言:javascript复制
  "scripts": {
  	"build":"webpack --mode production",
  "},
  • webpack 配置文件默认叫 webpack.config.js webpack.file.js

默认导出的是配置文件

  • 入口
代码语言:javascript复制
module.exports={ //入口 entry:path.resolve(__dirname,'./src/index.js'), //写路径都采用绝对路径 }
  • 出口
代码语言:javascript复制
module.exports={ output:{ filename:"bundle.js", path:path.resolve(__dirname,"dist"); } }
  • 模式
代码语言:javascript复制
module.exports = { mode: "development" //当前是开发模式 }
代码语言:javascript复制
"scripts": { "build": "webpack", "dev":"webpack" }, //- 变量的形式

webpack.config.js

代码语言:javascript复制
module.exports = (env)=>{ //env 环境变量 console.log("mode",env) //函数要返回配置文件,没返回会采用默认配置 }

package.json

代码语言:javascript复制
"scripts": { "build": "webpack --env.production", "dev":"webpack --env.development" },

为了区分开发模式和生产模式 会新建一个 build 文件 新建一个基础配置 webpack.base.js

webpack.base.js webpack.dev.js webpack.prod.js通过--config 指定执行的文件是哪一个。

  • 可以在 base 文件合并
  • 可以创建 dev,prod 分别在这两个文件中合并 base
代码语言:javascript复制
"scripts": {
    "build": "webpack --env.production --config ./build/webpack.base.js",
    "dev": "webpack --env.development --config ./build/webpack.base.js"
},
  • 可以通过 webpack-merge 来合并配置文件
代码语言:javascript复制
npm i webpack-merge --save-dev

用法

代码语言:javascript复制
if(isDev){
  return merge(base,dev)
}else{
  return merge(base,prod)
}

如果是开发环境,要使用 webpack-dev-server

代码语言:javascript复制
npm i webpack-dev-server --save-dev

webpack-dev-server 是在内存中打包的不会产生实体

代码语言:javascript复制
 "scripts": {
    "build": "webpack --env.production --config ./build/webpack.base.js",
    "dev": "webpack-dev-server --env.development --config ./build/webpack.base.js"
  },
代码语言:javascript复制
module.exports={
    mode:"development",
    devServer:{  //开发服务的配置
       port:3000,
       compress:true, //gzip 可以提升返回页面的速度
       contentBase:path.resolve(__dirname,'../dist') //webpack启动服务会在dist目录下
    }
}
  • 在 dist 打包自动生成 html 文件并且引入打包后的 js 内容
代码语言:javascript复制
npm i html-webpack-plugin --save-dev

在根文件下创建 public 文件夹

代码语言:javascript复制
 plugins:[
         new HtmlWebpackPlugin({
             template:path.resolve(__dirname,'../public/index.html'),
             filename:"index.html",
             minify:!isDev&&{
                 removeAttributeQuotes:true,  //去掉双引号
                 collapseWhitespace:true   //去掉空格
            }
         })
     ]
  • 每次打包重新生成 dist
代码语言:javascript复制
npm i clean-webpack-plugin --save-dev
代码语言:javascript复制
  //每次打包先清空dist文件夹
  new CleanWebpackPlugin({
       cleanOnceBeforeBuildPatterns: ['**/*']   //打包之前清空目录  默认是这个配置  所有目录下的所有文件
  }),

代码转化

css

先解析 css

代码语言:javascript复制
// index.js
import './index.css'
//引入css

1.loader 的执行顺序 默认从下往上执行 从右往左执行

2.css-loader 会解析 css 语法 style-loader 会将解析的 css 变成 style 标签插入到页面中

3.解析 css 需要两个 css-loader style-loader

代码语言:javascript复制
npm i css-loader style-loader --save-dev
代码语言:javascript复制
转化什么文件 用什么去转  使用那些loader
loader写法 可以是[] 也可以是{}也可以是""
rules:[
  {
   test:/.css$/,
   use:['style-loader','css-loader']
  },
]

预处理器

scss node-sass sass-loader

代码语言:javascript复制
npm i node-sass sass-loader --save-dev
代码语言:javascript复制
匹配到scss结尾的文件使用sass-loader来调用node-sass处理sass文件
{
test:/.scss$/,
use:['style-loader','css-loader','sass-loader']
}

less less-loader

stylus stylus-loader

如果 css 里引入了 scss 文件

代码语言:javascript复制
rules:[
  {
    test:/.css$/,
    use:['style-loader',{
      loader:'css-loader',
      options:{
          importLoaders:1
      }
    },'sass-loader']
  },
]

css 加前缀

  • 自动加前缀
代码语言:javascript复制
npm i postcss-loader --save-dev
 npm i autoprefixer --save-dev

需要一个配置文件 post.config.js

代码语言:javascript复制
module.exports={
    plugins:[
        require("autoprefixer")
    ]
}

创建一个.browserslistrc 文件

代码语言:javascript复制
cover 95%
  • 这么写开发是 ok 的,但是怎么解决生产样式?
    • 解析 css 的时候就不能渲染 dom
    • 希望 css 可以和 js 一起加载 mini-css-extract-plugin 需要把 css 抽离
代码语言:javascript复制
npm i mini-css-extract-plugin --save-dev
代码语言:javascript复制
new MiniCssExtractPlugin({  //如果是开发模式就不要用抽离样式的插件
    filename:"css/main.css"
})
代码语言:javascript复制
{
  test: /.css$/,
  use: [
    isDev?'style-loader':MiniCssExtractPlugin.loader,
     {
    loader: 'css-loader',
    options: {
      importLoaders: 2
    }
  }, 'postcss-loader', 'sass-loader']
}

webpack.prod.js

代码语言:javascript复制
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const TerserJSPlugin = require('terser-webpack-plugin');
module.exports={
    mode:"production",
    optimization: {  //优化项
        minimizer:[  //可以放置压缩方案
            new OptimizeCSSAssetsPlugin(),  //用了这个 js也得手动压缩
            new TerserJSPlugin()
        ]
    },
}

图片

  • 压缩图片
代码语言:javascript复制
 npm i file-loader --save-dev
 npm i url-loader --save-dev
代码语言:javascript复制
{
	test:/.(woff|ttf|eot|svg)/,
	use:"file-loader"
},
{
	test: /.(jpe?g|png|gif|jpg)$/,
	use: {
		loader: "url-loader",
		//如果大于100k的图片继续使用file-loader
		options: {
			name: 'image/[contentHash].[ext]',
			limit: 100 * 1024
		}
	}
	//file-loader  默认的功能是拷贝的功能
	//我希望是当前比较小的转化成base64 比以前大 好处就是不用发http请求
}

js

  • es6es5 但是有些 api 不是 es6 语法比如装饰器 类的属性
  • babel 转化功能 vue-cli 基于 babel6 来实现的,但是现在最新 babel 是 babel7
    • @babel/core 核心模块
    • @babel/preset-env 把 es6 转化成 es5
    • babel-loader 是 babel 和 webpack 的桥梁

总结:默认会调用@babel/core 来转化代码 转化的时候用@babel/preset-env 将 es6 转化成 es5

代码语言:javascript复制
  { //解析js文件 调用@babel/core
      test:/.js$/,
      use:"babel-loader"
  },
  • 创建 .babelrc文件默认是 options 的配置
代码语言:javascript复制
{
    "presets:[
        "@babel/preset-env"  //从下到上执行 这个是插件包
    ],
    "plugins":[  //从上到下执行   这个是单个插件

    ]
}
  • 解析提案语法 类的属性
代码语言:javascript复制
npm i @babel/plugin-proposal-class-properties -D
代码语言:javascript复制
"plugins":[  //从上到下执行
       ["@babel/plugin-proposal-class-properties",{"loose":true}]
    ]
  • loose:true 表示宽松 this.a=1
  • loose:false Object.definedProperty

解析装饰器

代码语言:javascript复制
npm i @babel/plugin-proposal-decorators --save-dev
  • 必须在@babel/plugin-proposal-class-properties 上面执行
代码语言:javascript复制
"plugins":[  //从上到下执行
       ["@babel/plugin-proposal-decorators",{"legacy":true}],
       ["@babel/plugin-proposal-class-properties",{"loose":true}]
    ]
  • 解析高级语法 使用的 api 自动转化 并且是按需加载
代码语言:javascript复制
"presets":[
        ["@babel/preset-env",{
            "usageBuitIns":"usage"   //按需加载
        }]  //从下到上执行
    ],
  • 节约代码大小
代码语言:javascript复制
npm install --save-dev @babel/plugin-transform-runtime
npm install --save @babel/runtime

解析jsx

代码语言:javascript复制
npm i @babel/preset-react --save-dev

解析ts

  • ts-loader 使用 typescript
  • babel7 @babel/preset-typescript 和 typescript 库没有关系
代码语言:javascript复制
npm i typescript
npx typescript -init 生成一个typescript文件

解析vue

  • vue.shims.d.ts
代码语言:javascript复制
declare module "*.vue"{
    import Vue from "vue";
    export default Vue
}
代码语言:javascript复制
npm i vue-loader vue-template-compiler -D
代码语言:javascript复制
{
	test:/.vue$/,
	use:"vue-loader"
},
const VueLoaderPlugin = require("vue-loader/lib/plugin");
new VueLoaderPlugin(),
  • vuets
代码语言:javascript复制
npm i vue-property-decorator --save-dev
代码语言:javascript复制
["@babel/preset-typescript",{
	"allExtensions":true
}]

最后

了解了上面的这些webpack,基本上就可以搭建我们的开发环境了,本文结束,有什么问题和有错误的地方,欢迎大家的留言和评论,还有后续更新,下期更加精彩

0 人点赞