webpack4 に基づいて反応スキャフォールディングを構築する方法のプロセス分析

不言
リリース: 2018-07-26 11:59:08
オリジナル
2508 人が閲覧しました

この記事で共有する内容は、webpack4 に基づいて反応スキャフォールディングを構築する方法のプロセス分析です。次に、困っている友人を助けることを願って、具体的な内容を見てみましょう。

react-sample-javascript

react-router-dom、redux、webpack 4を使用したReact 16.0ボイラープレート(JavaScript用)
githubプロジェクトアドレス

プロジェクトの初期化

統一された標準化されたコード形式

  1. 設定 .editorconfig により IDE が統一されます (コードを参照).editorconfig 使得IDE的方式统一 (见代码)

  2. 配置 .eslintrc.js 使得代码规范统一 (见代码)

    预期功能

  3. 管理资源: 能加载css、sccc、less、以及静态文件

  4. 管理输出:将打包后的静态文件输出至static目录下,以各自的文件类型管理

  5. dev:使用source map,方便调试时代码定位

  6. dev:配置devServer,并配置热替换,热加载,自动刷新,自动打开浏览器,并预留proxyTable

  7. dev:设置默认打开8080,被占用则寻找下一个空接口

  8. production:代码分离,打包css文件,css代码压缩,js代码压缩,输出到模板html,配置gzip

  9. analysis::使用BundleAnalyzerPlugin 分析打包后的性能

    目录结构

  • 首先使用npm init 初始化一个包含package.json的根目录

:.
│  .babelrc             #babel的规则以及插件
│  .editorconfig        #IDE/编辑器相关的配置
│  .eslintignore        #Eslint忽视的目录
│  .eslintrc.js         #Eslint的规则和插件
│  .gitignore           #Git忽视的目录
│  .postcssrc.js        #postcss的插件
│  package-lock.json
│  package.json         #项目相关的包
│  README.md
│  yarn.lock
│
├─build                 #webpack相关的配置
│      utils.js         #webpack配置中的通用方法
│      webpack.base.conf.js #webpack的基础配置
│      webpack.dev.conf.js  #webpack的开发环境配置
│      webpack.prod.conf.js #webpack的生产环境配置
│
└─src                   #主目录,业务代码
    │  app.css
    │  App.js
    │  favicon.ico
    │  index.ejs
    │  index.js
    │
    └─assets            #静态目录,存放静态资源
        │  config.json
        │
        └─img
                logo.svg
ログイン後にコピー

安装依赖

  • eslint-loader

  • eslint

  • eslint-config-airbnb

  • eslint-plugin-import

  • eslint-friendly-formatter

  • eslint-plugin-flowtype

  • eslint-plugin-jsx-a11y

  • eslint-plugin-react

  • babel-polyfill

  • webpack

  • jest

  • friendly-errors-webpack-plugin 编译提示的webpack插件

  • html-webpack-plugin 新建html入口文件的webpack插件

  • copy-webpack-plugin webpack配置合并模块

  • webpack-merge webpack配置合并模块

  • webpack-dev-server

  • webpack-bundle-analyzer

  • webpack-cli

  • portfinder 寻找接口的插件

  • extract-text-webpack-plugin

  • node-notifier

  • optimize-css-assets-webpack-plugin

  • autoprefixer

  • mini-css-extract-plugin

  • autoprefixer

  • css-loader

  • less-loader

  • postcss-loader

  • postcss-import

  • postcss-loader

  • style-loader

  • babel-core

  • babel-eslint

  • babel-loader

  • babel-plugin-transform-runtime

  • babel-plugin-import

  • babel-preset-env

  • babel-preset-react

  • babel-polyfill

  • url-loader

  • cross-env

  • file-loader

yarn add eslint eslint-loader eslint-config-airbnb eslint-plugin-import eslint-friendly-formatter eslint-plugin-flowtype eslint-plugin-jsx-a11y eslint-plugin-react babel-polyfill webpack jest webpack-merge copy-webpack-plugin html-webpack-plugin friendly-errors-webpack-plugin webpack-dev-server webpack-bundle-analyzer webpack-cli portfinder extract-text-webpack-plugin node-notifier optimize-css-assets-webpack-plugin autoprefixer mini-css-extract-plugin autoprefixer css-loader less-loader postcss-loader postcss-import postcss-loader style-loader babel-core babel-eslint babel-loader babel-plugin-transform-runtime babel-plugin-import babel-preset-env babel-preset-react babel-polyfill url-loader cross-env file-loader -D
ログイン後にコピー

项目配置

webpack 基础配置

  1. 为了控制开发环境和生产环境,我们可以新建build文件夹。分别书写开发环境和生产环境的webpack配置文件,这样也更可以方便我们分别控制生产环境和开发环境。

  2. 为了提高代码的复用率,也为了区别 基础配置个性配置 ,可以分别新建webpack.basewebpack.devwebpack.prod三个配置文件。首先配置最基础的entry(入口)和output(出口)。

module.exports = {
  context: path.resolve(__dirname, '../'),  //绝对路径。__dirname为当前目录。
    //基础目录用于从配置中解析入口起点。因为webpack配置在build下,所以传入 '../'
  entry: {
    app: ('./src/index.js') //项目的入口
  },
  output: {
    path: path.resolve(__dirname, '../dist'),
    filename: '[name].[hash:8].js',
    publicPath: '/',
    libraryTarget: 'umd',
  },
}
ログイン後にコピー

entry

entry可以分别为字符串、数组和对象。

倘若应用只有一个单一的入口,entry的值可以使用任意类型,不会影响输出结果。

// entry为字符串
{
    entry: './src/index.js',
    output: {
        path: '/dist',
        filename: 'bundle.js'
    }
}
// 结果会生成 '/dist/bundle.js'
ログイン後にコピー
// entry为数组,可以添加多个彼此不互相依赖的文件。结合output.library选项,如果传入数组,则只导出最后一项。
{
    //如果你在html文件里引入了'bable-polyfill',可以通过数组将它加到bundle.js的最后。
    entry: ['./src/index.js', 'babel-polyfill'] ,
    output:{
        path: '/dist',
        filename: 'bundle.js'
    }
}
ログイン後にコピー
// entry为对象,可以将页面配置为多页面的而不是SPA,有多个html文件。通过对象告诉webpack为每个入口,成一个bundle文件。
// 多页面的配置,可能还要借助于HtmlWebpackPlugin,来指定每个html需要引入的js
{
    entry: {
        index: './src/index.js'
        main: './src/index.js'
        login: './src/login.js'
    }
    output:{
        path: '/dist/pages'
        filename: '[name]-[hash:5].js' //文件名取自'entry'对象的键名,为了防止推送代码后浏览器读缓存,故再生成的文件之后加上hash码。
    }
}
// 会分别生成index.js,main.js,login.js三个文件
ログイン後にコピー

关于 webpack构建多页面 可以参考这篇文章。不过现在webpack4.x也是一次断崖式升级,感兴趣的同学可以自行搜索。

// entry也可以传入混合类型
{
    entry:{
        vendor: ['jquery','amap','babel-polyfill'] //也可以借助CommonsChunkPlugin提取vendor的chunk。
        index: './src/index.js'
    }
    output: {
        path: '/dist'
        filename: '[name]-[hash:5].js'
    }
}
ログイン後にコピー

CommonsChunkPlugin在webpack4.0之后移除了,可以使用splitChunksPlugin代替。

output

output最基础的两个配置为 pathfilename

  • path 告诉 webpack的输出目录在那里,一般我们会设置在根目录的 dist 文件夹;

  • filename 用于指定输出文件的文件名,如果配置了创建了多个单独的 chunk 则可以使用[name].[hash]

  • 🎜Configuration .eslintrc.js によりコード仕様が統一されます (コードを参照)🎜🎜期待される機能🎜< /li >🎜🎜リソースの管理: css、sccc、less、および静的ファイルをロードできます🎜🎜🎜出力の管理: パッケージ化された静的ファイルを静的ディレクトリに出力し、それぞれのファイルタイプに従って管理します🎜 🎜🎜dev: ソース マップを使用して、デバッグ中のコードの位置決めを容易にします🎜🎜🎜dev: devServer を構成し、ホット リプレースメント、ホット ロード、自動リフレッシュを構成し、ブラウザーを自動的に開き、proxyTable を予約します🎜 > 🎜🎜dev: デフォルトで 8080 を開くように設定します。占有されている場合は、次の空のインターフェイスを探します🎜🎜🎜制作: コード分離、CSS ファイルのパッケージ化、CSS コード圧縮、JS コード圧縮、テンプレート HTML への出力、 gzip を設定します🎜< /li>🎜🎜分析:: BundleAnalyzerPlugin を使用してパッケージングのパフォーマンスを分析します🎜🎜ディレクトリ構造🎜
      🎜🎜最初に npm を使用しますinit を使用して、.json のルート ディレクトリを含むパッケージを初期化します🎜
     output: {
        path: path.resolve(__dirname, &#39;../dist&#39;),
        filename: &#39;[name].[hash:8].js&#39;,
        publicPath: &#39;/&#39;,
      },
    ログイン後にコピー
    ログイン後にコピー
    🎜インストールの依存関係🎜
      🎜🎜eslint-loader🎜🎜🎜 eslint🎜🎜 🎜eslint-config-airbnb🎜🎜🎜eslint-plugin-import🎜🎜🎜eslint-フレンドリーフォーマッタ🎜🎜🎜eslint-plugin-flowtype🎜 🎜🎜eslint -plugin-jsx-a11y🎜🎜🎜eslint-plugin-react🎜🎜🎜babel-polyfill🎜🎜🎜webpack🎜🎜🎜 jest🎜🎜 🎜friends-errors-webpack-plugin コンパイルプロンプト用の Webpack プラグイン🎜🎜🎜html-webpack-plugin 作成用の Webpack プラグイン新しい HTML エントリ ファイル🎜🎜🎜copy-webpack-plugin webpack 構成マージ モジュール🎜🎜🎜webpack-merge webpack 構成マージ モジュール</ code>🎜</li>🎜🎜webpack-dev -server🎜</li>🎜🎜webpack-bundle-analyzer🎜</li>🎜🎜webpack-cli🎜</li>🎜🎜portfinder インターフェースを見つけるプラグイン🎜 </li>🎜🎜extract-text-webpack-plugin 🎜</li>🎜🎜node-notifier🎜</li>🎜🎜optimize-css-assets-webpack-plugin🎜</li>🎜🎜autoprefixer🎜</ li>🎜🎜mini-css-extract-plugin🎜</li>🎜🎜autoprefixer🎜</li>🎜🎜css-loader🎜</li>🎜🎜less-loader🎜</li>🎜🎜postcss-loader🎜 </li>🎜🎜postcss-import🎜</li>🎜🎜postcss-loader🎜</li>🎜🎜style-loader🎜</li>🎜🎜babel-core🎜</li>🎜🎜babel-eslint🎜 </li>🎜🎜babel-loader🎜</li >🎜🎜babel-plugin-transform-runtime🎜</li>🎜🎜babel-plugin-import🎜</li>🎜🎜babel-preset-env🎜</ li>🎜🎜babel-preset-react🎜</li>🎜🎜babel-polyfill🎜</li>🎜🎜url-loader🎜</li>🎜🎜cross-env🎜</li>🎜🎜file-loader🎜 </li></ul><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:js;toolbar:false;">resolve: { // 自动解析文件扩展名(补全文件后缀)(从左-&gt;右) // import hello from &amp;#39;./hello&amp;#39; (!hello.js? -&gt; !hello.jsx? -&gt; !hello.json) extensions: [&amp;#39;.js&amp;#39;, &amp;#39;.jsx&amp;#39;, &amp;#39;.json&amp;#39;], alias: { &amp;#39;@&amp;#39;: resolve(&amp;#39;src&amp;#39;) } },</pre><div class="contentsignin">ログイン後にコピー</div></div><div class="contentsignin">ログイン後にコピー</div></div>🎜プロジェクト構成🎜 🎜webpackの基本構成🎜🎜🎜🎜 開発環境と本番環境を制御するために、新しいビルドフォルダーを作成できます。開発環境と本番環境の Webpack 設定ファイルを別々に記述することで、本番環境と開発環境を個別に制御することが容易になります。 🎜</li>🎜🎜 コードの再利用率を向上させ、<code>基本構成個人用構成を区別するために、新しい webpack.base< を作成できます。 /code それぞれ >、<code>webpack.dev、および webpack.prod の 3 つの構成ファイル。まず、最も基本的な入力と出力を構成します。 🎜
      noParse: function(content) {
        return /jquery|lodash/.test(content);
      }
      ログイン後にコピー
      ログイン後にコピー

      entry

      🎜entry はそれぞれ文字列、配列、オブジェクトにすることができます。 🎜🎜アプリケーションにエントリが 1 つしかない場合、エントリ値はどのようなタイプでもよく、出力結果には影響しません。 🎜
      module: {
          rules: [
          {
              test: /\.(js|jsx)$/,
              exclude: /node_modules/,
              enforce: &#39;pre&#39;,
              use: [{
                loader: &#39;babel-loader&#39;,
              }, {
                loader: &#39;eslint-loader&#39;, // 指定启用eslint-loader
                options: {
                  formatter: require(&#39;eslint-friendly-formatter&#39;),
                  emitWarning: false
                }
              }]
            },
          {
              test: /\.css$/,
              include: /node_modules/,
              use: [
                MiniCssExtractPlugin.loader,
                &#39;css-loader&#39;,
                {
                  loader: &#39;postcss-loader&#39;,
                  options: {
                    plugins: () => [autoprefixer({ browsers: &#39;last 5 versions&#39; })],
                    sourceMap: false,
                  },
                },
              ],
            },
            {
              test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
              loader: &#39;url-loader&#39;,
              options: {
                limit: 10000,
                name: (&#39;assets/img/[name].[hash:7].[ext]&#39;)
              }
            },
            {
              test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
              loader: &#39;url-loader&#39;,
              options: {
                limit: 10000,
                name: (&#39;assets/media/[name].[hash:7].[ext]&#39;)
              }
            },
            {
              test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
              loader: &#39;url-loader&#39;,
              options: {
                limit: 10000,
                name: (&#39;assets/fonts/[name].[hash:7].[ext]&#39;)
              }
            }
          ]
          }
      ログイン後にコピー
      ログイン後にコピー
      // package.json
      "scripts": {
          "start": "webpack-dev-server --mode development --config build/webpack.dev.conf.js",
      }
      // 设置当前的mode为development,同样这个配置也可以写在webpack.dev.conf.js中。然后使用build目录下的webpack.dev.conf.js 来配置相关的webpack。
      ログイン後にコピー
      ログイン後にコピー
      devServer: {
          clientLogLevel: &#39;warning&#39;,
          historyApiFallback: true, //在开发单页应用时非常有用,它依赖于HTML5 history API,如果设置为true,所有的跳转将指向index.html
          contentBase: path.resolve(__dirname, &#39;../src&#39;),
          compress: true,
          hot: true, // 热加载
          inline: true, //自动刷新
          open: true, //自动打开浏览器
          host: HOST||&#39;localhost&#39;,
          port: PORT,
          overlay: { warnings: false, errors: true }, // 在浏览器上全屏显示编译的errors或warnings。
          publicPath: &#39;/&#39;,
          proxy: {},
          quiet: true, // necessary for FriendlyErrorsPlugin // 终端输出的只有初始启动信息。 webpack 的警告和错误是不输出到终端的
          watchOptions: {
            poll: false
          }
        },
        plugins: [
          new webpack.DefinePlugin({
            ...process.env
          }),
          //开启HMR(热替换功能,替换更新部分,不重载页面!)
          new webpack.HotModuleReplacementPlugin(),// HMR shows correct file names in console on update.
          //显示模块相对路径
          new webpack.NamedModulesPlugin(),
          //不显示错误信息
          new webpack.NoEmitOnErrorsPlugin(),
          // https://github.com/ampedandwired/html-webpack-plugin
          ]
      ログイン後にコピー
      ログイン後にコピー
      🎜 webpack を使用して複数のページを構築する方法については、この記事を参照してください。ただし、webpack 4.x は崖っぷちのアップグレードでもあり、興味のある学生は自分で検索できます。 🎜
      // 设置代码分离的输出目录
      output: {
          path: path.resolve(__dirname, &#39;../dist&#39;),
          filename: (&#39;js/[name].[hash:8].js&#39;),
          chunkFilename: (&#39;js/[name]-[id].[hash:8].js&#39;)
        },
       // 代码分离
       optimization: {
          runtimeChunk: {
            name: "manifest"
          },
          splitChunks: {
            chunks: &#39;all&#39;
          }
        },
      ログイン後にコピー
      ログイン後にコピー

      🎜CommonsChunkPlugin は webpack 4.0 の後に削除されました。代わりに、splitChunksPlugin を使用できます。 🎜

      出力

      🎜 出力の 2 つの最も基本的な構成は、pathfilename です。 🎜
        🎜 🎜path は、出力ディレクトリの場所を webpack に伝えます。一般に、dist フォルダーをルート ディレクトリに設定します。 code > 出力ファイルのファイル名を指定するために使用されます。複数の個別の chunk が設定されている場合、プレースホルダー [name].[hash] を使用して、それぞれを確認できます。ファイルには一意の名前が付いています。
      • 另一个常见配置 publicPath 则是用于更加复杂的场景。举例:在本地时,你可能会使用 ../assets/test.png 这种url来载入图片。而在生产环境下,你可能会使用CDN或者图床的地址。那么就需要配置 publicPath = "http://cdn.example.com/assets/" 来实现生产模式下编译输出文件时自动更新url。

       output: {
          path: path.resolve(__dirname, &#39;../dist&#39;),
          filename: &#39;[name].[hash:8].js&#39;,
          publicPath: &#39;/&#39;,
        },
      ログイン後にコピー
      ログイン後にコピー

      resolve

      resolve常用的两个配置为 aliasextensions

      • alias 创建import或者require的别名

      • extensins 自动解析文件拓展名,补全文件后缀

      resolve: {
          // 自动解析文件扩展名(补全文件后缀)(从左->右)
          // import hello from &#39;./hello&#39;  (!hello.js? -> !hello.jsx? -> !hello.json)
          extensions: [&#39;.js&#39;, &#39;.jsx&#39;, &#39;.json&#39;],
          alias: {
            &#39;@&#39;: resolve(&#39;src&#39;)
          }
        },
      ログイン後にコピー
      ログイン後にコピー

      module

      module的选项决定了如何处理项目中的不同类型的模块。其中常用的有 rulesnoParese 两个配置项。

      • noParese 是为了防止weback解析与所有与rule相匹配的文件。目的是,忽略大型的library可以提高构建性能。

      noParse: function(content) {
        return /jquery|lodash/.test(content);
      }
      ログイン後にコピー
      ログイン後にコピー
      • rules 用于在创建模块是,匹配规则数组,以确定哪些规则能够对module应用loader,或者是修改parser。

      module: {
          rules: [
          {
              test: /\.(js|jsx)$/,
              exclude: /node_modules/,
              enforce: &#39;pre&#39;,
              use: [{
                loader: &#39;babel-loader&#39;,
              }, {
                loader: &#39;eslint-loader&#39;, // 指定启用eslint-loader
                options: {
                  formatter: require(&#39;eslint-friendly-formatter&#39;),
                  emitWarning: false
                }
              }]
            },
          {
              test: /\.css$/,
              include: /node_modules/,
              use: [
                MiniCssExtractPlugin.loader,
                &#39;css-loader&#39;,
                {
                  loader: &#39;postcss-loader&#39;,
                  options: {
                    plugins: () => [autoprefixer({ browsers: &#39;last 5 versions&#39; })],
                    sourceMap: false,
                  },
                },
              ],
            },
            {
              test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
              loader: &#39;url-loader&#39;,
              options: {
                limit: 10000,
                name: (&#39;assets/img/[name].[hash:7].[ext]&#39;)
              }
            },
            {
              test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
              loader: &#39;url-loader&#39;,
              options: {
                limit: 10000,
                name: (&#39;assets/media/[name].[hash:7].[ext]&#39;)
              }
            },
            {
              test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
              loader: &#39;url-loader&#39;,
              options: {
                limit: 10000,
                name: (&#39;assets/fonts/[name].[hash:7].[ext]&#39;)
              }
            }
          ]
          }
      ログイン後にコピー
      ログイン後にコピー

      例如上述代码,就使用eslint-lodaerbabel-loader 处理了除了node_modules 以外的 js||jsx。同时配置了,解析图片、视频、字体文件等的解析,当rules匹配到的文件时,小于10000 byte 时,采用url-loader解析文件。(因为base64会让图片的体积变大,所以当文件较大时,使用base64并不明智)

      Webpack开发配置

      因为在webpack 4.X 中使用了流行的 ”约定大于配置“ 的做法,所以在新加入配置项 mode ,可以告知webpack使用相应模式的内置优化。

      选项描述
      development会将process.env.NODE_ENV 的值设为 development 。启用NamedChunksPluginNamedMoudulesPlugin
      production会将process.env.NODE_ENV 的值设为 production 。启用FlagDependencyUsagePluginFlagIncludedChunksPluginModuleConcatenationPluginNoEmitOnErrorsPluginOccurrenceOrderPluginSideEffectsFlagPluginUglifyJsPlugin

      如果我们只设置NODE_ENV,则不会自动设置 mode

      在开发时,我们往往希望能看到当前开发的页面,并且能热加载。这时,我们可以借助webpack-dev-server 这个插件,来在项目中起一个应用服务器。

      // package.json
      "scripts": {
          "start": "webpack-dev-server --mode development --config build/webpack.dev.conf.js",
      }
      // 设置当前的mode为development,同样这个配置也可以写在webpack.dev.conf.js中。然后使用build目录下的webpack.dev.conf.js 来配置相关的webpack。
      ログイン後にコピー
      ログイン後にコピー
      devServer: {
          clientLogLevel: &#39;warning&#39;,
          historyApiFallback: true, //在开发单页应用时非常有用,它依赖于HTML5 history API,如果设置为true,所有的跳转将指向index.html
          contentBase: path.resolve(__dirname, &#39;../src&#39;),
          compress: true,
          hot: true, // 热加载
          inline: true, //自动刷新
          open: true, //自动打开浏览器
          host: HOST||&#39;localhost&#39;,
          port: PORT,
          overlay: { warnings: false, errors: true }, // 在浏览器上全屏显示编译的errors或warnings。
          publicPath: &#39;/&#39;,
          proxy: {},
          quiet: true, // necessary for FriendlyErrorsPlugin // 终端输出的只有初始启动信息。 webpack 的警告和错误是不输出到终端的
          watchOptions: {
            poll: false
          }
        },
        plugins: [
          new webpack.DefinePlugin({
            ...process.env
          }),
          //开启HMR(热替换功能,替换更新部分,不重载页面!)
          new webpack.HotModuleReplacementPlugin(),// HMR shows correct file names in console on update.
          //显示模块相对路径
          new webpack.NamedModulesPlugin(),
          //不显示错误信息
          new webpack.NoEmitOnErrorsPlugin(),
          // https://github.com/ampedandwired/html-webpack-plugin
          ]
      ログイン後にコピー
      ログイン後にコピー

      其实在开发时,我们可以设置 contentBase: &#39;/src&#39;contentBase 指定了devServer能访问的资源地址。因为我们开发时,资源大部分都放在src目录下,所以可以直接指定资源路径为src目录。因为我们在webpack基础配置时,配置了 output 输出为 dist 目录,所以我们也可以在devServer里,设置 contentBasedist 目录。不过此时需要使用copyWebpackPlugin将一些静态资源复制到 dist 目录下,手动新建dist目录,并复制也可以。

      另外,当使用 history 路由时,要配置 historyApiFallback = true ,以此让服务器放弃路由权限,交由前端路由。而是用 hash 路由则不需要此配置。

      项目进阶

      生产环境配置

      在使用webpack 4.x 的 mode 配置之后,需要我们手动配置的项已经减少了很多,像js代码压缩这种工具 UglifyJsPlugin 就已经不用手动去配置。但是像很多前面提到的 代码分离css代码提取和压缩html的生成 以及 复制静态资源 还需要我们手动配置。

      代码分离

      // 设置代码分离的输出目录
      output: {
          path: path.resolve(__dirname, &#39;../dist&#39;),
          filename: (&#39;js/[name].[hash:8].js&#39;),
          chunkFilename: (&#39;js/[name]-[id].[hash:8].js&#39;)
        },
       // 代码分离
       optimization: {
          runtimeChunk: {
            name: "manifest"
          },
          splitChunks: {
            chunks: &#39;all&#39;
          }
        },
      ログイン後にコピー
      ログイン後にコピー

      css代码压缩

      借助 MiniCssExtractPlugin 来实现压缩css和提取css。因为 MiniCssExtractPlugin 无法与style-loader 共存,所以我们需要判断当前环境是生成环境还是开发环境。

      我们可以新建一个util.js的文件,在webpack当中一些共用的方法。考虑使用个别配置字段 extract 来配置使用何种方式来配置css-loader。参见 util.js 代码。

      new MiniCssExtractPlugin({
            filename: &#39;css/[name].[hash:8].css&#39;,
            chunkFilename: &#39;css/[name]-[id].[hash:8].css&#39;,
          }),
      ログイン後にコピー

      生成HTML

      使用htmlWebpackPlugin,配合ejs。可以使控制html 的生成。通过配置的方式,生成html。因为 HtmlWebpackPlugin 本身可以解析ejs,所以不需要单独引入ejs的loader。

      new HtmlWebpackPlugin({
            filename: &#39;index.html&#39;,
            template: &#39;./src/index.ejs&#39;, // 设置目录
            title: &#39;React Demo&#39;,
            inject: true, // true->&#39;head&#39; || false->&#39;body&#39;
            minify: {
              //删除Html注释
              removeComments: true,
              //去除空格
              collapseWhitespace: true,
              //去除属性引号
              removeAttributeQuotes: true
              // more options:
              // https://github.com/kangax/html-minifier#options-quick-reference
            },
            // necessary to consistently work with multiple chunks via CommonsChunkPlugin
            chunksSortMode: &#39;dependency&#39;
          }),
      ログイン後にコピー
      <!DOCTYPE html>
      <html>
      <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <meta name="robots" content="noindex, nofollow">
      
        <title><%= htmlWebpackPlugin.options.title %></title>
        <link rel="shortcut icon" href="/favicon.ico" type="image/x-icon">
        <link rel="icon" href="/favicon.ico" type="image/x-icon">
      
        <% for (var chunk in htmlWebpackPlugin.files.css) { %>
        <link rel="preload" href="<%= htmlWebpackPlugin.files.css[chunk] %>"  as="style">
        <% } %>
        <% for (var chunk in htmlWebpackPlugin.files.chunks) { %>
        <link rel="preload" href="<%= htmlWebpackPlugin.files.chunks[chunk].entry %>" as="script">
        <% } %>
      
        <base href="/">
      </head>
      <body>
      <p id="root"></p>
      </body>
      <style type="text/css">
        body {
          font-family: &#39;Source Sans Pro&#39;,&#39;Helvetica Neue&#39;,Helvetica,Arial,sans-serif;
        }
      </style>
      </html>
      ログイン後にコピー

      复制静态目录

      将所以可能被请求的静态文件,分别放在assets目录下。那么在打包后,为了保证目录能正常访问(不使用CDN等加载静态资源时),我们可以配置 publicPath = &#39;/&#39; 。然后借助于 CopyWebpackPlugin 实现资源复制。

      new CopyWebpackPlugin([{
            from: &#39;./src/assets/&#39;,
            to: &#39;assets&#39;
          }]),
      ログイン後にコピー

      src/assets 复制到 dist/assets 目录下

      开启打包分析

      借助插件 BundleAnalyzerPlugin 直接在plugins中创建该插件:

      // webpack.prod.conf.js
      const BundleAnalyzerPlugin = process.env.NODE_ENV=== &#39;analysis&#39; ? require(&#39;webpack-bundle-analyzer&#39;).BundleAnalyzerPlugin:null
      process.env.NODE_ENV=== &#39;analysis&#39; ? new BundleAnalyzerPlugin() : ()=>{}
      ログイン後にコピー

      在package.json 中可做如下配置:

      "scripts": {
          "analysis": "cross-env NODE_ENV=analysis webpack -p --mode production --progress --config ./build/webpack.prod.conf.js ",
        },
      ログイン後にコピー

      通过注入环境变量,来控制是否运行打包分析。

      ssh部署

      打包后的dist文件夹,可以直接借助 node 的 ssh-node ,直接部署到服务器指定的目录下。 ssh-node既支持ssh,也支持密码登录。建议可以为在每个项目下,新建一个.ssh文件,存放项目的私钥。代码如下:

      // usage: https://www.npmjs.com/package/node-ssh
      var path, node_ssh, ssh, fs, opn, host
      
      fs = require(&#39;fs&#39;)
      path = require(&#39;path&#39;)
      node_ssh = require(&#39;node-ssh&#39;)
      opn = new require(&#39;opn&#39;)
      ssh = new node_ssh()
      host = &#39;localhost&#39;
      var localDir = &#39;./dist&#39;
      var remoteDir = &#39;/opt/frontend/new&#39;
      var removeCommand = &#39;rm -rf ./*&#39;
      var pwdCommand = &#39;pwd&#39;
      
      ssh.connect({
        host: host,
        username: &#39;root&#39;,
        port: 22,
        // password,
        privateKey: "./.ssh/id_rsa",
      })
        .then(function() {
          ssh.execCommand(removeCommand, { cwd:remoteDir }).then(function(result) {
            console.log(&#39;STDOUT: &#39; + result.stdout)
            console.log(&#39;STDERR: &#39; + result.stderr)
            ssh.putDirectory(localDir, remoteDir).then(function() {
              console.log("The File thing is done")
              ssh.dispose()
              opn(&#39;http://&#39;+host, {app:[&#39;chrome&#39;]})
            }, function(error) {
              console.log("Something&#39;s wrong")
              console.log(error)
              ssh.dispose()
            })
          })
        })
      ログイン後にコピー

      此时,在命令行直接 node deploy.js 就可以运行以上脚本,我们也可以添加一个build + deploy的script脚本,便于启动。

      "scripts": {
          "depoly": "npm run build && node ./deploy.js",
      }
      ログイン後にコピー

      相关推荐:

      详解React 快速上手脚手架 create-react-app

      简单搭建一个react项目

      以上がwebpack4 に基づいて反応スキャフォールディングを構築する方法のプロセス分析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!