Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
397 views
in Technique[技术] by (71.8m points)

jquery - Using webpack with an existing PHP and JS project

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 entry point for my project resources, manage js dependencies with node js package manager, run tasks as minify js css, image re-size...etc. And improve the browser loading time required to load a single page.

I came across the webpack tutorials and got to install it and install its dev-server, but the problem is that I am not able to understand how I will convert all my current js scripts and css links in the project (where I have a lot of jquery and CSS libraries used to provide multiple features in the project) to use webpack.

Do I have to rewrite all my JS and CSS files in a way that suits webpack? How do I make a successful migration?

Besides, I am not able to run my current php application on the webpack dev-server, is it meant to run there in the first place? It is only listing the directories of the project in the meantime.

I have created a test index.js file and used the following webpack configuration:

var path = require('path');
var webpack = require('webpack');

module.exports =
{
    entry: [
        './public/js/index.js',
        'webpack/hot/dev-server',
        'webpack-dev-server/client?http://localhost:8080'
    ],
    plugins: [
      new webpack.HotModuleReplacementPlugin()
    ],
    output: {
        path: path.join(__dirname, "public/dist/js"),
        publicPath : "http://localhost:8080/my_proj/public/dist/js",
        filename: "bundle.js"
    }

};

I added the bundle.js to my script loads just for testing as follows hoping that the application will run on the webpack dev-server:

<script type="text/javascript" src="public/dist/js/bundle.js"></script>
<script type="text/javascript" src="public/js/jquery.min.js"></script>
<script type="text/javascript" src="public/js/jquery.migrate.js"></script>
<script type="text/javascript" src="public/js/jquery.bxslider.min.js"></script>
<script type="text/javascript" src="public/js/jquery.appear.js"></script>
<script type="text/javascript" src="public/js/jquery.countTo.js"></script>
<script type="text/javascript" src="public/js/bootstrap.js"></script>

Please help me understand the concept here and how can I make this migration successfully?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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' <script> tag.

Congratulations, you've got a working webpack setup!

Dive deeper

This mini-tutorial really just scraped the surface of what you can do with webpack. It gives you a pretty solid foundation for your configuration which you now can fill with whatever you need. And that will actually be quite a lot of stuff.

I'll list a few more things you may want to enhance, with some links to read through.

webpack Concepts

If you want to use webpack, it can be hard to do so if you don't know about its underlying concepts. Juho Veps?l?inen created a great guide on getting started with webpack which helped me a whole lot. He's also a webpack core contributor so you can be sure he knows what he's talking about.

Especially loaders are a concept you'll really need to know.

Many of the hints on this list are also explained there.

Read more: SurviveJS – webpack tutorial

Code Splitting

It does what the name's saying: You might not want to pack all your JavaScript into one bulky output file.

It's a job webpack does for you to split off parts of your bundle which you only need on certain pages of your application.

Also, depending on how frequently you're working on your project's JavaScript, it might be a good idea to split off third party code from your bundle for caching purposes.

Read more: webpack Documentation – Code Splitting

Caching

You may want to enhance your site's caching behaviour by adding a hash to your bundled file names which depends on their content. This will create (for example) a script.31aa1d3cad014475a618.js instead of a scripts.js.

That file can then be cached indefinitely because as soon as its contents change, the file name will change as well.

Your PHP code might then use the webpack-manifest-plugin to gain access to the generated file names.

Read more:

Transpiling

In case you want to use modern ES2015 code in your site's JavaScript (and are targeting non-evergreen browsers), you'll want to transpile them down to regular ES5. (If the term "ES2015" does not make any sense to you, you're most likely not using it and can ignore this paragraph.)

Read more:


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...