webpack VS parcel

parcel 最大的特色就是簡單,內置常見依賴,默認支持模塊熱替換和引用 CSS 文件。css

webpack 4.0 在優化構建性能的同時,也添加了許多默認配置。(重大變化:點我)html

特性 webpack parcel
文件名添加 hash 支持 不支持
構建時處理 css 需配置
tree-shaking production 下支持 不支持
構建時預編譯 production 下支持 不支持
生成 html 文件並引用資源 需配置,且默認 CSS 在 JS 文件中 自動生成,CSS 是獨立的文件
熱模塊更新(HMR) 需配置 開發模式下默認開啓

如下針對構建工具經常使用功能,對 webpackparcel 進行對比node

引入文件

webpack

const path = require('path');

module.exports = {
    mode: 'development', // development / production
    entry: './src/index.js',
    output: {
        filename: 'bundle-[hash].js',
        path: path.resolve(__dirname, 'dist')
    }
};

兩個模式(主要區別就是前一個開發模式不壓縮,生產模式壓縮)react

  • development:Enables NamedModulesPlugin
  • production:Enables UglifyJsPlugin, ModuleConcatenationPlugin(預編譯) and NoEmitOnErrorsPlugin

parcel

開發模式(支持熱更新,並開啓服務):webpack

parcel index.html --out-dir ../dist/

生產模式(代碼壓縮):es6

parcel build index.js --out-dir ../dist

資源管理

webpack

webpack 只構建 JS 文件,因此 CSS 文件都會以字符串形式保存在 JS 文件中(固然必要時也能夠單獨配置,拆分 css 文件),並需手動引用到 index.html 文件中。web

對 CSS 預處理,都須要配置 webpack.config.js 文件,添加 loadertypescript

module: {
    rules: [{
        test: /\.css$/,
        use: [
              'style-loader',
              'css-loader'
        ]
      }]
}

parcel

在 js 文件中引入的 CSS 會自動構建並引用到 html 裏,還支持預處理器如:less sass stylusnpm

這裏舉 sass 爲例json

  1. 本地安裝依賴包 npm install node-sass
  2. 在 js 文件中引入 sass 的文件 import './index.sass'

執行 parcel,sass 文件將會被構建成 css 文件名引用到 index.html 中

資源轉換

webpack

  1. babel

    安裝依賴包

    npm install babel-loader babel-core babel-preset-env webpack

    配置 webpack.config.js 文件

    module: {
        rules: [{
            test: /\.js$/,
            exclude: /(node_modules|bower_components)/,
            use: {
                loader: 'babel-loader',
                options: {
                    presets: ['babel-preset-env']
                }
            }
        }]
    }
  2. postcss

    安裝

    npm i -D postcss-loader

    配置 postcss.config.js 文件

    module.exports = {
        parser: false,
        plugins: {
            'postcss-import': {},
            'postcss-cssnext': {},
            'cssnano': {},
            'autoprefixer': true
        }
    }
  3. typescript

    安裝依賴包

    npm install --save-dev typescript ts-loader

    建立 tsconfig.json 文件

    {
        "compileOptions": {
            "outDir": "./dist/",
            "noImplicitAny": true,
            "module": "es6",
            "target": "es5",
            "jsx": "react",
            "allowJs": true
        }
    }

    建立 index.ts 文件

    function greeter(person: string) {
        return "Hello, " + person;
    }
    
    let user = "Jane User";
    
    document.body.innerHTML = greeter(user);

    配置 webpack.config.js

    const path = require('path');
    
    module.exports = {
        mode: 'development',
        entry: './src/index.ts',
        module: {
            rules: [{
                test: /\.css$/,
                use: [
                    'style-loader',
                    'css-loader'
                ]
            }, {
                test: /.tsx?$/,
                use: 'ts-loader',
                exclude: /node_modules/
            }]
        },
        resolve: {
            extensions: [ '.tsx', '.ts', '.js' ]
        },
        output: {
            filename: 'bundle.js',
            path: path.resolve(__dirname, 'dist')
        },
    };

parcel

  1. babel

    npm i babel-preset-env
    
    // create a .babelrc:
    {
      "presets": ["env"]
    }
  2. PostCSS

    npm i postcss-modules autoprefixer
    
    {
      "plugins": {
        "autoprefixer": {
          "grid": true
        }
      }
    }
  3. typescript

    只需安裝 typescript 便能使用

    npm i typescript

代碼拆分(分塊加載)

webpack

有三種方法來實現

  1. webpack.config.js 中配置 entry point

    const path = require('path');
    const HTMLWebpackPlugin = require('html-webpack-plugin');
    module.exports = {
        mode: 'development',//'production',
        entry: {
            index: './src/index.js',
            another: './src/util.js'
        },
        plugins: [
            new HTMLWebpackPlugin({ // 生成 html 文件,並引入入口文件
                title: 'Code Splitting'
            })
        ],
        output: {
            filename: '[name].bundle.js',
            path: path.resolve(__dirname, 'dist')
        },
    };
  2. 使用 splitChunks 提取公共組件

    webpack 4 中,CommonChunkPlugin 將被配置項 optimization.splitChunks

    const path = require('path');
    const HTMLWebpackPlugin = require('html-webpack-plugin');
    module.exports = {
        mode: 'development',
        entry: {
            index: './src/index.js',
            another: './src/another.js'
        },
        plugins: [
            new HTMLWebpackPlugin({ // 生成 html 文件,並引入入口文件
                title: 'Code Splitting'
            })
        ],
        optimization: {
            splitChunks: {
                chunks: "all",
                name: 'common',
            }
        },
        output: {
            filename: '[name].bundle.js',
            path: path.resolve(__dirname, 'dist')
        },
    };
  3. 動態引用,import 異步加載

    異步加載文件,並返回 promise,若是多個異步importchunkname 一致,則構建時會合並這個文件

    配置 webpack.config.js

    const path = require('path');
    const HTMLWebpackPlugin = require('html-webpack-plugin');
    
    module.exports = {
        mode: 'development',//'production',
        entry: {
            index: './src/index.js',
            another: './src/another.js'
        },
        output: {
            filename: '[name].bundle.js',
            chunkFilename: '[name].bundle.js',
            path: path.resolve(__dirname, 'dist')
        },
    };

    引用方法

    function getComponent() {
        return import(/* webpackChunkName: "lodash" */ 'lodash').then(_ => {
          // todo
        })
    }
    getComponent().then(component => {})

    async 寫法

    async function getComponent() {
        const _ = await import(/* webpackChunkName: "lodash" */ 'lodash');
        // todo
    }
    getComponent().then(component => {});

parcel

util.js 文件

export function a() {
    console.log('a');
}

export function b() {
    console.log('b');
}

index.js 文件

import('./util').then(function (util) {
    util.a();
});

模塊熱更新(HMR)

webpack

安裝依賴

npm install --save-dev webpack-dev-server

配置 webpack.config.js

const path = require('path');
const HTMLWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack');

module.exports = {
    mode: 'development',//'production',
    entry: {
        index: './src/index.js',
        another: './src/another.js'
    },
    devServer: {
        contentBase: './dist',
        hot: true
    },
    plugins: [
        // new CleanWebpackPlugin(['dist']),
        new HTMLWebpackPlugin({
            title: 'Hot Module Replacement'
        }),
        new webpack.NamedModulesPlugin(),
        new webpack.HotModuleReplacementPlugin()
    ],
    output: {
        filename: '[name].bundle.js',
        chunkFilename: '[name].bundle.js',
        path: path.resolve(__dirname, 'dist')
    },
};

配置 package.json

"scripts": {
    "start": "webpack-dev-server --open"
}

執行運行代碼

npm start

parcel

開發模式下自動默認支持

參考資料

  1. parcel 官網,https://en.parceljs.org
  2. webpack 官網,https://en.parceljs.org
  3. 《webpack 4.0.0-beta.0 新特性介紹》,開元,2018.02.07,http://jdc.jd.com/archives/21...
相關文章
相關標籤/搜索