zoukankan      html  css  js  c++  java
  • 手摸手:3秒打包一个three.js项目(有物证)

    关于 webpack 相关的文章太多了,何不一起从零开始手写一个配置呢?

    真的3秒能打包一个three.js项目吗?真的,后面会提供源文件地址哦。

    要打包的项目是这个样子的。

    从零开始

    关于 three.js 的安装和使用部分都省略。

    首先是最基础的。我们需要安装

    1. cross-env 目前最流行的运行跨平台设置和使用环境变量的脚本
    2. webpack + webpack-cli + webpack-dev-server:三'贱'客,项目必备

    参考常规webpack配置结构需要3个最基础文件:

    1. webpack 基础配置文件,暂命名为 webpack.base.js
    2. webpack 开发配置文件,暂命名为 webpack.dev.js
    3. webpack 打包配置文件,暂命名为 webpack.prod.js

    当然,需要把 devprod 中的配置和 base 的配置合并起来,安装个webpack-merge 吧。

    然后配置一下最熟悉的脚本运行环节吧。通过--config来对标配置文件,通cross-env 设置环境变量

    "dev": "cross-env NODE_ENV=dev webpack-dev-server --config script/webpack.dev.js",
    "build": "cross-env NODE_ENV=prod webpack --config script/webpack.prod.js"
    

    好的,初期准备工作都OK开始配置环节。

    开始配置

    首先是webpack的出入口。出口设置为 dist 环节简单直接上代码。

      {
        entry: './src/index.js',
        output: {
          filename: '[name].[hash:8].js',
          path: rootResolve('dist'),
          publicPath: '/'
        },
      }
    

    顺便配置下别名。依然可以直接上代码

      resolve: {
        extensions: ['.js', '.json'],
        alias: {
          '@': rootResolve('src'),
          '@assets': rootResolve('src/assets'),
        }
      }
    

    然后是关键环节:loaderplugins

    关于 loader:

    • 样式上使用 less
      • 需要通过less-loader 解析 less 因为 webpack 只能读懂js
      • 解析完成再通过 postcss-loader 加上浏览器前缀
      • 再通过css-loader 解析css代码中的 url@import语法
      • 最后,通过MiniCssExtractPlugin.loader 生成 .css文件
    • JS 文件使用 babel-loader,关于 babel 文章太多了,暂略
      • 顺便使用 HappyPack 进行优化加速
      • 为什么不选 thread-loader 呢? (因为名字不好听 - -! 怪我咯)
    • 其他文件,用 url-loader 咯。

    然后 loader 配置就是这样的

    {
      test: /.less$/,
      exclude: /(node_modules|bower_components)/,
      loaders: [{
        loader: MiniCssExtractPlugin.loader,
        options: {
          esModule: true,
          hmr: process.env.NODE_ENV === 'dev', // 热更新
          // publicPath: '../',
        }
      }, 'css-loader', 'postcss-loader', 'less-loader']
    },
    {
      test: /.m?js$/,
      exclude: /(node_modules|bower_components)/,
      loader: 'happypack/loader',
      options: {
        id: 'babel',
      }
    },
    {
      test: /.(png|jpe?g|gif)(?.*)?$/,
      use: [{
        loader: 'url-loader',
        options: {
          limit: 8192,
          name: 'assets/img/[hash:8].[ext]'
        }
      }]
    }
    

    关于插件部分,首先是配合上面 loader的相关插件:HappyPackMiniCssExtractPlugin

    new MiniCssExtractPlugin({
      filename: "css/[name].[hash:8].css", // css 路径
    }),
    new HappyPack({
      id: 'babel',
      loaders: [{
        loader: 'babel-loader',
        options: {
          presets: ['@babel/preset-env'],
          cacheDirectory: true
        }
      }]
    })
    

    当然,我想知道运行和打包的进度: ProgressPlugin,顺便弄个 DefinePlugin 工程化必备插件。最后webpack生成后的代码注入不能少了 HtmlWebpackPlugin

    然后 base 文件的插件结构是这样的

    plugins: [
      new webpack.ProgressPlugin(),
      new webpack.DefinePlugin({
        NODE_ENV: JSON.stringify(process.env.NODE_ENV), // 当前使用环境
        VERSION: JSON.stringify('0.1.0'),
      }),
      new MiniCssExtractPlugin({
        filename: "css/[name].[hash:8].css", // css 路径
        // chunkFilename: "[id].css",
      }),
      new HappyPack({
        id: 'babel',
        loaders: [{
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env'],
            cacheDirectory: true
          }
        }]
      }),
      new HtmlWebpackPlugin({ template: './src/index.html' })
    ]
    

    开发环境配置

    首先开发环境 api 代理必不可少。那么就是 devServer.proxy了,顺便再定义下开发环境端口号。

    devServer: {
      contentBase: path.join(__dirname, "dist"),
      compress: true,
      port: 3333
    }
    

    目前也没有太多事情,那么 merge 下再配个 HotModuleReplacementPlugin

    merge(base, {
      mode: 'development',
      plugins: [
      ],
      devServer: {
        contentBase: rootResolve("src"),
        compress: true,
        port: 3333
      },
      plugins: [
        new webpack.HotModuleReplacementPlugin()
      ]
    })
    

    打包环境

    打包环境主要做了这几件事情

    1. 打包优化
    2. 分类文件
    3. 删除冗余

    首先是 dll

    1. 定义 dll 配置文件。 比如:webpack.dll.config.js
      1. 需要定义要打包的库和打包的出口
      2. 命名生成后的dll模块的详细要点文件 manifest.dll.json

    那么 webpack.dll.config.js 内容应该是这样的

    {
    	// 你想要打包的模块的数组
    	entry: {
    		vendor: ['three']
    	},
    	output: {
    		filename: '[name].dll.js',
    		path: distResolve('dll'), // 打包后文件输出的位置
    		library: '[name]_library'
    		// 这里需要和webpack.DllPlugin中的`name: '[name]_library',`保持一致。
    	},
    	plugins: [
    		new webpack.DllPlugin({
    			name: '[name]_library',
    			path: distResolve('dll/manifest.dll.json'),
    			context: __dirname
    		})
    	]
    }
    
    1. 通过 DllReferencePlugin + json文件 把 dll模块的详细要点告诉 webpack

    prod 文件中添加 plugins

    new webpack.DllReferencePlugin({
      context: __dirname,
      manifest: require(distResolve('./dll/manifest.dll.json'))
    })
    
    1. 添加脚本运行配置
    "dll": "webpack --config script/webpack.dll.config.js",
    

    运行下 npm run dll,在 dist/dll 目录下生成dll相关文件,那么 dll 配置也完成了。顺便做一些清理工作,用下 CleanWebpackPlugin

    new CleanWebpackPlugin({
      cleanOnceBeforeBuildPatterns: [
        'assets', 'js', 'css', 'index.html', '*.js',
        '!manifest.dll.json', '!vendor.dll.js' // 不删除 dll 文件
      ],
    })
    

    然后是代码优化,其实当 mode: 'production' 时已经做了很多代码优化相关的事情了。(我不管,我就是要优化 - -!

    做一下 js的并行压缩吧

    optimization: {
      minimizer: [
        new TerserWebpackPlugin({
          parallel: true,  // 启用并行压缩
          cache: true,    // 启用缓存
        }),
        new OptimizeCssAssetsPlugin({ // 压缩css
          cssProcessorOptions: {
            safe: true
          }
        })
      ],
      runtimeChunk: true, // 自动拆分runtime文件
      splitChunks: {
        chunks: 'async',
        minSize: 30000,
        automaticNameDelimiter: '~',
        automaticNameMaxLength: 30,
        cacheGroups: {
          defaultVendors: {
            test: /[\/]node_modules[\/]/,
            priority: -10
          },
          default: {
            minChunks: 2,
            priority: -20,
            reuseExistingChunk: true
          }
        }
      },
    }
    

    欧耶,再配置下js的打包后路径就好了

    output: { // JS 路径
      path: distResolve(),
      filename: 'js/[id].[chunkhash].js',
      chunkFilename: 'js/[name].[chunkhash].js'
    },
    

    最后 mergebase 配置。在 dev 时做过了... 省略。

    至此,Webpack配置已经大部分完成了,运行npm run build打包代码,1、2、3。 3秒打包完成了。

    为什么只需要3秒呢?虽然上面的配置确实做了很多优化,但是大部分事情都被表象迷惑了,具体为何下一章见。

    最后

    1. 源码地址 https://github.com/zhongmeizhi/three-demo
    2. 更多实战项目:https://github.com/zhongmeizhi/z-ui
    3. 一个字一个字码出来的文章,原创不易,点个赞呗。
    4. 欢迎关注公众号「前端进阶课」认真学前端,一起进阶。

  • 相关阅读:
    实操记录之-----Ant Design of Vue 增强版动态合并单元格,自动根据数据进行合并,可自定义横纵向合并
    实操好用~~~~~antd 中 Table表格动态合并~~~
    超级容易理解的函数节流(throttle)
    Flask框架
    Celery框架
    redis数据库如何用Django框架缓存数据
    luffyapi项目 --短信认证的基本操作
    DRF之Jwt 实现自定义和DRF小组件及django-filter插件的使用
    Auth主件的(RBAC) 六表
    DRF之三大认证
  • 原文地址:https://www.cnblogs.com/zhongmeizhi/p/12409926.html
Copyright © 2011-2022 走看看