Using webpack with an existing PHP and JS project

前端 未结 2 2007
孤独总比滥情好
孤独总比滥情好 2020-12-12 10:27

I have an existing PHP project with jquery and bootstrap, not using any front-end framework.

I am trying to use webpack module bundler in order to create a single en

2条回答
  •  有刺的猬
    2020-12-12 11:08

    First, to answer your smaller questions:

    • No, you're not supposed to run your PHP application through a webpack dev server. Explained in the Live Reloading section below.
    • No, you won't have to rewrite your assets. Probably. See the CSS and Edge Cases sections below.

    Disclaimer: I'll only take on a small fraction of your question. Its scope is just way too broad to be packed into just one StackOverflow answer.

    I will only get in touch with

    • setting up a development and a production environment for webpack
    • bundling your first JavaScript

    which should give you a foundation to build on.

    I'll also mention some things you may want to add and link according resources to read through.

    So, let's go.

    Requirements

    I assume you have Node.js and npm installed on your machine and roughly know how to use them.

    I also assume you have webpack and webpack-cli installed as (dev) dependencies of your project (not just globally):

    npm install --save-dev webpack webpack-cli
    

    Update: Earlier versions of this answer did not require installing webpack-cli. As of version 4 (February 2018), webpack's CLI resides in its own package, hence the additional required package.

    Set up development and a production workflow

    You usually want to do stuff differently in development than in production (minifying in production, live-reloading in development, ...)

    To achieve that, we'll want to split up our configuration files.

    Prepare the directory structure

    Let's agree to ignore the webpack config from your question. We'll start all over, we'd have to change almost everything anyway.

    First, create a build folder inside your project root. Build-related stuff will go there, since we don't want to pollute your project's root folder with config files. (You're free to name this folder differently, but keep track of that during this tutorial.)

    Create a config.base.js, a config.production.js and a config.development.js file inside that folder.

    Great, we have config files for two build chains now. The configurations are still empty though, so let's now fill them with some basic logic.

    Install webpack-merge

    But first, we'll need to install webpack-merge.

    npm install --save-dev webpack-merge
    

    This package allows us to deeply merge multiple webpack configurations. We want to use it to create webpack configurations depending on our current environment.

    Adjust your configuration

    Now adjust your build/config.base.js:

    module.exports = {
      // We'll place webpack configuration for all environments here
    }
    

    The file does obviously just export an empty object right now, but we'll need that for the following steps.

    Put this code in your build/config.production.js:

    const merge = require('webpack-merge')
    
    module.exports = merge(require('./config.base.js'), {
      mode: 'production'
    
      // We'll place webpack configuration for production environment here
    })
    

    And almost the same code goes into your build/config.development.js:

    const merge = require('webpack-merge')
    
    module.exports = merge(require('./config.base.js'), {
      mode: 'development',
      watch: true
    
      // All webpack configuration for development environment will go here
    })
    

    I guess it's pretty intuitive what this does:

    Using webpack with the config.development.js configuration will fetch the common configuration and merge its own config declaration in.

    Update: The mode option in the above config files was added in webpack 4 (released February 2018). It sets a bunch of sensible defaults for development and production bundles.

    Now running the process would look like this from the command line:

    npx webpack --config build/config.development.js
    
    # If the above doesn't work, you probably have an older version of npm (< 5.1) installed
    # While npx is a really great tool, you can of course still call the path of the webpack executable manually:
    
    node_modules/.bin/webpack --config build/config.development.js
    

    ...and vice versa for the production environment.

    That command is rather clunky to use, but no worries, we'll address that later.

    Make some helper files

    There are information we'll be wanting to centralize to make them easily exchangeable. File paths are such a thing. So let's extract them.

    Create a paths.js in your build folder and have it export some paths we'll want to use later:

    const path = require('path')
    
    // I'm really just guessing your project's folder structure from reading your question,
    // you might want to adjust this whole section
    module.exports = {
      // The base path of your source files, especially of your index.js
      SRC: path.resolve(__dirname, '..', 'public'),
    
      // The path to put the generated bundle(s)
      DIST: path.resolve(__dirname, '..', 'public', 'dist'),
    
      /*
      This is your public path.
      If you're running your app at http://example.com and I got your DIST folder right,
      it'll simply be "/dist".
      But if you're running it locally at http://localhost/my/app, it will be "/my/app/dist".
    
      That means you should probably *not* hardcode that path here but write it to a
      machine-related config file. (If you don't already have something like that,
      google for "dotenv" or something similar.)
      */
      ASSETS: '/dist'
    }
    

    Create aliases

    As mentioned above, we could technically run our build chain in development mode like this:

    npx webpack --config build/config.development.js
    

    That's an uncomfortably verbose command though, so let's change that.

    It's way more convenient to run your build process via npm scripts. Add one script per environment to your package.json like this:

    {
      "scripts": {
        "dev": "webpack --config build/config.development.js",
        "prod": "webpack --config build/config.production.js"
      }
    }
    

    Now you can run your build chains with npm run dev resp. npm run prod – which is much easier to memorize and faster to type.

    ...as soon as there'es anything to build, of course.

    Bundle JavaScript

    Okay, that was actually a fair amount of work without achieving too much so far.

    So let's start with something more exciting: We'll define a JavaScript entry point.

    Define an entry point

    Put the following code into your build/config.base.js (replacing the existing code entirely):

    const path = require('path')
    const { SRC, DIST, ASSETS } = require('./paths')
    
    module.exports = {
      entry: {
        scripts: path.resolve(SRC, 'js', 'index.js')
      },
      output: {
        // Put all the bundled stuff in your dist folder
        path: DIST,
    
        // Our single entry point from above will be named "scripts.js"
        filename: '[name].js',
    
        // The output path as seen from the domain we're visiting in the browser
        publicPath: ASSETS
      }
    }
    

    Create the JavaScript file

    The above configuration expects an index.js to live in your SRC/js folder (as defined in the build/paths.js).

    Let's create that file with the following content:

    import './jquery.min.js'
    import './jquery.migrate.js'
    import './jquery.bxslider.min.js'
    import './jquery.appear.js'
    import './jquery.countTo.js'
    import './bootstrap.js'
    

    As you can see, the index.js just imports all of the files you want to use.

    If you now run

    npm run prod
    

    from your terminal, a scripts.js file will be created in your DIST folder. You can include that into your markup with a plain ol'

提交回复
热议问题